From d67322725858657226d999bbf114059b1b21ba04 Mon Sep 17 00:00:00 2001 From: ashnamehrotra Date: Mon, 22 Jan 2024 19:24:22 +0000 Subject: [PATCH] deploy: ac614ffb19678f29f9c1ac54edb70a1d39e10d71 --- docs/404.html | 17 +- docs/architecture.html | 27 +-- docs/assets/css/styles.28354d54.css | 1 - docs/assets/css/styles.e36959ff.css | 1 + docs/assets/js/0390b328.2bf1bb4b.js | 1 - docs/assets/js/0390b328.50c3d7e8.js | 1 + docs/assets/js/0480b142.32575a54.js | 1 - docs/assets/js/0480b142.652e6bd1.js | 1 + docs/assets/js/07e6d80c.5396be34.js | 1 + docs/assets/js/07e6d80c.53b2fbd7.js | 1 - docs/assets/js/096837f0.771b8b12.js | 1 - docs/assets/js/096837f0.c3c4e65e.js | 1 + docs/assets/js/0d9a188d.1186d693.js | 1 - docs/assets/js/0d9a188d.65d8092e.js | 1 + docs/assets/js/0fb10398.6b984536.js | 1 + docs/assets/js/0fb10398.a6ee55bc.js | 1 - docs/assets/js/101be56a.8ca0113a.js | 1 - docs/assets/js/101be56a.d26e4b44.js | 1 + docs/assets/js/11d58a17.c673924e.js | 1 + docs/assets/js/11d58a17.d706823d.js | 1 - docs/assets/js/12682444.4416d267.js | 1 - docs/assets/js/12682444.bf167c14.js | 1 + docs/assets/js/1426.be67a35e.js | 1 + docs/assets/js/1772.61f6592f.js | 1 + docs/assets/js/17896441.5c745bdc.js | 1 - docs/assets/js/17896441.6d94e406.js | 1 + docs/assets/js/1a4e3797.be02ef92.js | 2 - .../js/1a4e3797.be02ef92.js.LICENSE.txt | 1 - docs/assets/js/1a4e3797.cdef43d5.js | 2 + .../js/1a4e3797.cdef43d5.js.LICENSE.txt | 1 + docs/assets/js/1b064146.869a4cad.js | 1 + docs/assets/js/1b064146.b78fd6fa.js | 1 - docs/assets/js/1be78505.f8b40e6f.js | 1 - docs/assets/js/1c30975d.740a287b.js | 1 + docs/assets/js/1c30975d.c04b6b62.js | 1 - docs/assets/js/1dba1ecf.4673d8c6.js | 1 - docs/assets/js/1dba1ecf.d433b521.js | 1 + docs/assets/js/20cdecc4.5375813a.js | 1 - docs/assets/js/20cdecc4.7ca62856.js | 1 + docs/assets/js/22539a87.31d0f153.js | 1 + docs/assets/js/22539a87.ca79dac7.js | 1 - docs/assets/js/24e97898.33651e6b.js | 1 + docs/assets/js/24e97898.70b78e51.js | 1 - docs/assets/js/29ca1a0e.1424cf4d.js | 1 + docs/assets/js/29ca1a0e.4d91cc87.js | 1 - docs/assets/js/2c8b636f.733d78b2.js | 1 + docs/assets/js/2c8b636f.b2f1412e.js | 1 - docs/assets/js/2f4673e5.187f339b.js | 1 + docs/assets/js/2f4673e5.680a6df6.js | 1 - docs/assets/js/30fb9660.273b686e.js | 1 + docs/assets/js/30fb9660.e3f700a3.js | 1 - docs/assets/js/34f2f592.2d883d56.js | 1 + docs/assets/js/34f2f592.86fae0eb.js | 1 - docs/assets/js/3847b3ea.43247e52.js | 1 + docs/assets/js/3847b3ea.5b5ccf89.js | 1 - docs/assets/js/3a1ed2bb.12630a9f.js | 1 - docs/assets/js/3a1ed2bb.18ad5ad5.js | 1 + docs/assets/js/3b8c55ea.4ab0bf60.js | 1 + docs/assets/js/3b8c55ea.d50f0d5a.js | 1 - docs/assets/js/3e4c86d4.0b3602b2.js | 1 + docs/assets/js/3e4c86d4.eaafa28e.js | 1 - docs/assets/js/3fcb412e.54c127a8.js | 1 + docs/assets/js/3fcb412e.d61d4ab6.js | 1 - docs/assets/js/422308df.b9cbb4dc.js | 1 + docs/assets/js/422308df.c748cc2d.js | 1 - docs/assets/js/4351fb58.2ba23a80.js | 1 - docs/assets/js/4351fb58.d28caec9.js | 1 + docs/assets/js/44b2adf6.28ae2c3b.js | 1 - docs/assets/js/44b2adf6.95473760.js | 1 + docs/assets/js/48ae5635.4f79be50.js | 1 - docs/assets/js/48ae5635.ae8b4c4e.js | 1 + docs/assets/js/4972.e3352a90.js | 1 - docs/assets/js/4d54d076.6a163bd0.js | 1 - docs/assets/js/4d54d076.d5641f32.js | 1 + docs/assets/js/4eac74de.cd66025d.js | 1 + docs/assets/js/4eac74de.fb8596ee.js | 1 - docs/assets/js/4fa03c51.7f9609b5.js | 1 + docs/assets/js/4fa03c51.ad054cf8.js | 1 - docs/assets/js/4fb2362d.43d62e16.js | 1 - docs/assets/js/4fb2362d.5120e8b9.js | 1 + docs/assets/js/5281b7a2.981f96dc.js | 1 + docs/assets/js/5281b7a2.ceaf1ffc.js | 1 - docs/assets/js/5603335d.05cbde15.js | 1 - docs/assets/js/5603335d.b23ecd98.js | 1 + docs/assets/js/59e5a646.d59d85e0.js | 1 + docs/assets/js/59e5a646.e9edd18a.js | 1 - docs/assets/js/5af9b662.48bb081f.js | 1 + docs/assets/js/5af9b662.988a70e9.js | 1 - docs/assets/js/5bc37772.1188e660.js | 1 - docs/assets/js/5bc37772.c2ae9680.js | 1 + docs/assets/js/5c838b7d.8c56c538.js | 1 - docs/assets/js/5c838b7d.abeb9ef9.js | 1 + docs/assets/js/5e95c892.b00730d7.js | 1 + docs/assets/js/62c6dc45.beacabe7.js | 1 + docs/assets/js/62c6dc45.d4fbe534.js | 1 - docs/assets/js/6739d7ff.89c2e76b.js | 1 - docs/assets/js/6739d7ff.c14998ff.js | 1 + docs/assets/js/6780.2f5c1e5a.js | 1 - docs/assets/js/695a8bbb.23b6fade.js | 1 - docs/assets/js/695a8bbb.ab71b31c.js | 1 + docs/assets/js/6af0c1ea.4be63f6e.js | 1 - docs/assets/js/6af0c1ea.e59808b7.js | 1 + docs/assets/js/6b8e46b3.1f13278c.js | 1 + docs/assets/js/6b8e46b3.2a4f2d74.js | 1 - docs/assets/js/6ec64a11.ac3c351f.js | 1 - docs/assets/js/6ec64a11.e804f073.js | 1 + docs/assets/js/70b084fe.021d30e0.js | 1 - docs/assets/js/70b084fe.e3b3cc0e.js | 1 + docs/assets/js/7196cdd1.5bf303c3.js | 1 - docs/assets/js/7196cdd1.e3825316.js | 1 + docs/assets/js/72e14192.52383938.js | 1 + docs/assets/js/72e14192.5d76082f.js | 1 - docs/assets/js/72ffabc7.89379632.js | 1 + docs/assets/js/72ffabc7.d08704ae.js | 1 - docs/assets/js/7b11c903.40de134e.js | 1 + docs/assets/js/7b11c903.ce482ce3.js | 1 - docs/assets/js/7c6883b5.468dab34.js | 1 - docs/assets/js/7c6883b5.a26ba92b.js | 1 + docs/assets/js/7d415946.1d8d923e.js | 1 - docs/assets/js/7d415946.b8046362.js | 1 + docs/assets/js/7d6336d8.545b329a.js | 1 + docs/assets/js/7d6336d8.d9e3c66f.js | 1 - docs/assets/js/85c70040.6420b355.js | 1 + docs/assets/js/85c70040.e0419889.js | 1 - docs/assets/js/8c9fcf50.cf3bd3d7.js | 1 + docs/assets/js/8c9fcf50.e1bd2694.js | 1 - docs/assets/js/8cd4fd18.5d94802b.js | 1 + docs/assets/js/8cd4fd18.5dd67d55.js | 1 - docs/assets/js/8eef7690.687f1101.js | 1 - docs/assets/js/8eef7690.ca5fd282.js | 1 + docs/assets/js/8f41530a.3235cd00.js | 1 - docs/assets/js/8f41530a.d1d7746f.js | 1 + docs/assets/js/935f2afb.0a68307c.js | 1 + docs/assets/js/935f2afb.da0a9203.js | 1 - docs/assets/js/93bf47d2.597826fd.js | 1 + docs/assets/js/93bf47d2.cca23454.js | 1 - docs/assets/js/974203ee.4618b9f3.js | 1 - docs/assets/js/974203ee.db23a97e.js | 1 + docs/assets/js/9748995c.8c0b6d5e.js | 1 - docs/assets/js/9748995c.9c31807a.js | 1 + docs/assets/js/99ed3086.1ed71bcf.js | 1 + docs/assets/js/99ed3086.694e142d.js | 1 - docs/assets/js/9d55bf96.47c09e6a.js | 1 - docs/assets/js/9d55bf96.48d408b8.js | 1 + docs/assets/js/9dbb4f95.67a9bc2d.js | 1 + docs/assets/js/9dbb4f95.ea996f10.js | 1 - docs/assets/js/9e350ec0.513719f1.js | 1 - docs/assets/js/9e350ec0.5d832f0e.js | 1 + docs/assets/js/9ff53b5b.5c60e5b7.js | 1 - docs/assets/js/9ff53b5b.7090781c.js | 1 + docs/assets/js/a09c2993.479588b5.js | 1 - docs/assets/js/a09c2993.9909da7a.js | 1 + docs/assets/js/a683e47f.6b48266e.js | 1 + docs/assets/js/a683e47f.b8f20d95.js | 1 - docs/assets/js/a708fa78.2bb257f2.js | 1 - docs/assets/js/a708fa78.54aaa7fc.js | 1 + docs/assets/js/a7bd4aaa.45274bc2.js | 1 + docs/assets/js/a8f67d08.9df77a9f.js | 1 + docs/assets/js/a8f67d08.d837a742.js | 1 - docs/assets/js/a932041a.2d3e796f.js | 1 + docs/assets/js/a932041a.d5e014b0.js | 1 - docs/assets/js/a94703ab.5018fc8a.js | 1 + docs/assets/js/ae417a11.3d424f98.js | 1 + docs/assets/js/ae417a11.d3ca84d8.js | 1 - docs/assets/js/b0fc3de5.3454cfc2.js | 1 - docs/assets/js/b0fc3de5.be5ce799.js | 1 + docs/assets/js/b70ea2cb.1f9cdb37.js | 1 + docs/assets/js/b70ea2cb.99ee2f04.js | 1 - docs/assets/js/b7730d0d.1c52ffde.js | 1 - docs/assets/js/b7730d0d.88998729.js | 1 + docs/assets/js/b7cd4035.0ab6a66d.js | 1 - docs/assets/js/b7cd4035.d3c04a53.js | 1 + docs/assets/js/b9421f89.292245b3.js | 1 + docs/assets/js/b9421f89.bce75c8a.js | 1 - docs/assets/js/bacc1ae0.816015a9.js | 1 - docs/assets/js/bacc1ae0.c11996b0.js | 1 + docs/assets/js/bbedbacb.734bd7d6.js | 1 + docs/assets/js/bbedbacb.9fcac33b.js | 1 - docs/assets/js/bc344202.0b3ac2c6.js | 1 + docs/assets/js/bc344202.a00f1fb9.js | 1 - docs/assets/js/bc8dcae3.4c7ec3a0.js | 1 - docs/assets/js/bc8dcae3.deeb5da5.js | 1 + docs/assets/js/bdb5eb86.9d21e19a.js | 1 + docs/assets/js/bdb5eb86.b95ff3d4.js | 1 - docs/assets/js/bf5c5542.4f1330ce.js | 1 - docs/assets/js/bf5c5542.ec01ec49.js | 1 + docs/assets/js/bffae3e7.d211ec7b.js | 1 + docs/assets/js/bffae3e7.d34bc0df.js | 1 - docs/assets/js/c108e81c.3dfa39c8.js | 1 + docs/assets/js/c108e81c.619f3030.js | 1 - docs/assets/js/c12dc9fd.1b6a252d.js | 1 - docs/assets/js/c12dc9fd.ade4b346.js | 1 + docs/assets/js/c4f50fcb.b3a1918d.js | 1 - docs/assets/js/c4f50fcb.ddfb9faa.js | 1 + docs/assets/js/c66bbf8a.13446857.js | 1 + docs/assets/js/c66bbf8a.1acc839f.js | 1 - docs/assets/js/c698fe77.164c142f.js | 1 - docs/assets/js/c698fe77.a9373167.js | 1 + docs/assets/js/c73303db.0eee1cb1.js | 1 + docs/assets/js/c73303db.be916204.js | 1 - docs/assets/js/c853dc39.2fc0de50.js | 1 - docs/assets/js/c853dc39.861078cc.js | 1 + docs/assets/js/c9ca4745.da4f0967.js | 1 - docs/assets/js/c9ca4745.e2a7d363.js | 1 + docs/assets/js/d40dbec5.3ea65837.js | 1 - docs/assets/js/d40dbec5.8e7bd9d0.js | 1 + docs/assets/js/d7561401.2cac3291.js | 1 - docs/assets/js/d7561401.72651373.js | 1 + docs/assets/js/db59132a.6f50c1d0.js | 1 - docs/assets/js/db59132a.bdd9cb70.js | 1 + docs/assets/js/dbbf7db4.ad052b4c.js | 1 + docs/assets/js/dbbf7db4.c7332918.js | 1 - docs/assets/js/dc9281b9.7ca1886c.js | 1 + docs/assets/js/dc9281b9.8b8ee3c8.js | 1 - docs/assets/js/dea0f9ea.313a6052.js | 1 - docs/assets/js/dea0f9ea.7a05a9de.js | 1 + docs/assets/js/e1b2cf59.5eb99ea6.js | 1 + docs/assets/js/e1b2cf59.b8a8ffb4.js | 1 - docs/assets/js/e36340b6.4feb6f73.js | 1 + docs/assets/js/e36340b6.8972753a.js | 1 - docs/assets/js/e3d8f98f.a2c52a4d.js | 1 + docs/assets/js/e3d8f98f.c2802ab1.js | 1 - docs/assets/js/e7fdf6d9.94d9b31c.js | 1 + docs/assets/js/e7fdf6d9.de866fbb.js | 1 - docs/assets/js/ec0d5d9e.2c250436.js | 1 - docs/assets/js/ec0d5d9e.3d394cb4.js | 1 + docs/assets/js/ed8448fe.485bf575.js | 1 + docs/assets/js/ed8448fe.b3589d7f.js | 1 - docs/assets/js/efdb11b6.0bcb2915.js | 1 + docs/assets/js/efdb11b6.c5386572.js | 1 - docs/assets/js/f2ef54d0.06e099a0.js | 1 + docs/assets/js/f2ef54d0.4af2136b.js | 1 - docs/assets/js/fa2b770f.4d309065.js | 1 - docs/assets/js/fa2b770f.f4f734aa.js | 1 + docs/assets/js/faa9d310.5838e10c.js | 1 + docs/assets/js/faa9d310.9de6aa31.js | 1 - docs/assets/js/fc618254.c686b75c.js | 1 - docs/assets/js/fc618254.e65d5a68.js | 1 + docs/assets/js/fcff9033.00614336.js | 1 + docs/assets/js/fcff9033.b18535a7.js | 1 - docs/assets/js/fd1ae250.0fe36588.js | 1 - docs/assets/js/fd1ae250.8a9454eb.js | 1 + docs/assets/js/main.3fdea3bd.js | 2 - docs/assets/js/main.424bf04c.js | 2 + ...CENSE.txt => main.424bf04c.js.LICENSE.txt} | 47 ++--- docs/assets/js/runtime~main.3e75485d.js | 1 - docs/assets/js/runtime~main.7ab14693.js | 1 + docs/code-of-conduct.html | 22 +-- docs/contributing.html | 25 +-- docs/custom-scanner.html | 21 +-- docs/customization.html | 85 +++++++--- docs/exclusion.html | 22 +-- docs/faq.html | 25 +-- docs/index.html | 19 +-- docs/installation.html | 21 +-- docs/manual-removal.html | 30 ++-- docs/metrics.html | 24 +-- docs/next.html | 19 +-- docs/next/architecture.html | 27 +-- docs/next/code-of-conduct.html | 22 +-- docs/next/contributing.html | 25 +-- docs/next/custom-scanner.html | 21 +-- docs/next/customization.html | 85 +++++++--- docs/next/exclusion.html | 22 +-- docs/next/faq.html | 25 +-- docs/next/installation.html | 21 +-- docs/next/manual-removal.html | 30 ++-- docs/next/metrics.html | 24 +-- docs/next/quick-start.html | 41 +++-- docs/next/release-management.html | 81 +++++++-- docs/next/releasing.html | 44 +++-- docs/next/setup.html | 160 ++++++++++++++++-- docs/next/trivy.html | 18 +- docs/quick-start.html | 41 +++-- docs/release-management.html | 81 +++++++-- docs/releasing.html | 44 +++-- docs/search.html | 15 +- docs/setup.html | 160 ++++++++++++++++-- docs/sitemap.xml | 2 +- docs/trivy.html | 18 +- docs/v0.4.x.html | 19 +-- docs/v0.4.x/architecture.html | 28 +-- docs/v0.4.x/code-of-conduct.html | 22 +-- docs/v0.4.x/contributing.html | 25 +-- docs/v0.4.x/custom-scanner.html | 19 +-- docs/v0.4.x/customization.html | 23 +-- docs/v0.4.x/exclusion.html | 30 ++-- docs/v0.4.x/faq.html | 18 +- docs/v0.4.x/installation.html | 21 +-- docs/v0.4.x/manual-removal.html | 30 ++-- docs/v0.4.x/quick-start.html | 41 +++-- docs/v0.4.x/releasing.html | 73 ++++++-- docs/v0.4.x/setup.html | 160 ++++++++++++++++-- docs/v0.4.x/trivy.html | 24 +-- docs/v0.5.x.html | 19 +-- docs/v0.5.x/architecture.html | 28 +-- docs/v0.5.x/code-of-conduct.html | 22 +-- docs/v0.5.x/contributing.html | 25 +-- docs/v0.5.x/custom-scanner.html | 21 +-- docs/v0.5.x/customization.html | 23 +-- docs/v0.5.x/exclusion.html | 30 ++-- docs/v0.5.x/faq.html | 18 +- docs/v0.5.x/installation.html | 21 +-- docs/v0.5.x/manual-removal.html | 30 ++-- docs/v0.5.x/quick-start.html | 41 +++-- docs/v0.5.x/releasing.html | 73 ++++++-- docs/v0.5.x/setup.html | 160 ++++++++++++++++-- docs/v0.5.x/trivy.html | 24 +-- docs/v1.0.x.html | 19 +-- docs/v1.0.x/architecture.html | 27 +-- docs/v1.0.x/code-of-conduct.html | 22 +-- docs/v1.0.x/contributing.html | 25 +-- docs/v1.0.x/custom-scanner.html | 21 +-- docs/v1.0.x/customization.html | 85 +++++++--- docs/v1.0.x/exclusion.html | 22 +-- docs/v1.0.x/faq.html | 18 +- docs/v1.0.x/installation.html | 21 +-- docs/v1.0.x/manual-removal.html | 30 ++-- docs/v1.0.x/metrics.html | 24 +-- docs/v1.0.x/quick-start.html | 41 +++-- docs/v1.0.x/releasing.html | 39 +++-- docs/v1.0.x/setup.html | 160 ++++++++++++++++-- docs/v1.0.x/trivy.html | 18 +- docs/v1.1.x.html | 19 +-- docs/v1.1.x/architecture.html | 27 +-- docs/v1.1.x/code-of-conduct.html | 22 +-- docs/v1.1.x/contributing.html | 25 +-- docs/v1.1.x/custom-scanner.html | 21 +-- docs/v1.1.x/customization.html | 85 +++++++--- docs/v1.1.x/exclusion.html | 22 +-- docs/v1.1.x/faq.html | 25 +-- docs/v1.1.x/installation.html | 21 +-- docs/v1.1.x/manual-removal.html | 30 ++-- docs/v1.1.x/metrics.html | 24 +-- docs/v1.1.x/quick-start.html | 41 +++-- docs/v1.1.x/releasing.html | 39 +++-- docs/v1.1.x/setup.html | 160 ++++++++++++++++-- docs/v1.1.x/trivy.html | 18 +- docs/v1.2.x.html | 19 +-- docs/v1.2.x/architecture.html | 27 +-- docs/v1.2.x/code-of-conduct.html | 22 +-- docs/v1.2.x/contributing.html | 25 +-- docs/v1.2.x/custom-scanner.html | 21 +-- docs/v1.2.x/customization.html | 85 +++++++--- docs/v1.2.x/exclusion.html | 22 +-- docs/v1.2.x/faq.html | 25 +-- docs/v1.2.x/installation.html | 21 +-- docs/v1.2.x/manual-removal.html | 30 ++-- docs/v1.2.x/metrics.html | 24 +-- docs/v1.2.x/quick-start.html | 41 +++-- docs/v1.2.x/releasing.html | 39 +++-- docs/v1.2.x/setup.html | 160 ++++++++++++++++-- docs/v1.2.x/trivy.html | 18 +- 353 files changed, 3148 insertions(+), 1309 deletions(-) delete mode 100644 docs/assets/css/styles.28354d54.css create mode 100644 docs/assets/css/styles.e36959ff.css delete mode 100644 docs/assets/js/0390b328.2bf1bb4b.js create mode 100644 docs/assets/js/0390b328.50c3d7e8.js delete mode 100644 docs/assets/js/0480b142.32575a54.js create mode 100644 docs/assets/js/0480b142.652e6bd1.js create mode 100644 docs/assets/js/07e6d80c.5396be34.js delete mode 100644 docs/assets/js/07e6d80c.53b2fbd7.js delete mode 100644 docs/assets/js/096837f0.771b8b12.js create mode 100644 docs/assets/js/096837f0.c3c4e65e.js delete mode 100644 docs/assets/js/0d9a188d.1186d693.js create mode 100644 docs/assets/js/0d9a188d.65d8092e.js create mode 100644 docs/assets/js/0fb10398.6b984536.js delete mode 100644 docs/assets/js/0fb10398.a6ee55bc.js delete mode 100644 docs/assets/js/101be56a.8ca0113a.js create mode 100644 docs/assets/js/101be56a.d26e4b44.js create mode 100644 docs/assets/js/11d58a17.c673924e.js delete mode 100644 docs/assets/js/11d58a17.d706823d.js delete mode 100644 docs/assets/js/12682444.4416d267.js create mode 100644 docs/assets/js/12682444.bf167c14.js create mode 100644 docs/assets/js/1426.be67a35e.js create mode 100644 docs/assets/js/1772.61f6592f.js delete mode 100644 docs/assets/js/17896441.5c745bdc.js create mode 100644 docs/assets/js/17896441.6d94e406.js delete mode 100644 docs/assets/js/1a4e3797.be02ef92.js delete mode 100644 docs/assets/js/1a4e3797.be02ef92.js.LICENSE.txt create mode 100644 docs/assets/js/1a4e3797.cdef43d5.js create mode 100644 docs/assets/js/1a4e3797.cdef43d5.js.LICENSE.txt create mode 100644 docs/assets/js/1b064146.869a4cad.js delete mode 100644 docs/assets/js/1b064146.b78fd6fa.js delete mode 100644 docs/assets/js/1be78505.f8b40e6f.js create mode 100644 docs/assets/js/1c30975d.740a287b.js delete mode 100644 docs/assets/js/1c30975d.c04b6b62.js delete mode 100644 docs/assets/js/1dba1ecf.4673d8c6.js create mode 100644 docs/assets/js/1dba1ecf.d433b521.js delete mode 100644 docs/assets/js/20cdecc4.5375813a.js create mode 100644 docs/assets/js/20cdecc4.7ca62856.js create mode 100644 docs/assets/js/22539a87.31d0f153.js delete mode 100644 docs/assets/js/22539a87.ca79dac7.js create mode 100644 docs/assets/js/24e97898.33651e6b.js delete mode 100644 docs/assets/js/24e97898.70b78e51.js create mode 100644 docs/assets/js/29ca1a0e.1424cf4d.js delete mode 100644 docs/assets/js/29ca1a0e.4d91cc87.js create mode 100644 docs/assets/js/2c8b636f.733d78b2.js delete mode 100644 docs/assets/js/2c8b636f.b2f1412e.js create mode 100644 docs/assets/js/2f4673e5.187f339b.js delete mode 100644 docs/assets/js/2f4673e5.680a6df6.js create mode 100644 docs/assets/js/30fb9660.273b686e.js delete mode 100644 docs/assets/js/30fb9660.e3f700a3.js create mode 100644 docs/assets/js/34f2f592.2d883d56.js delete mode 100644 docs/assets/js/34f2f592.86fae0eb.js create mode 100644 docs/assets/js/3847b3ea.43247e52.js delete mode 100644 docs/assets/js/3847b3ea.5b5ccf89.js delete mode 100644 docs/assets/js/3a1ed2bb.12630a9f.js create mode 100644 docs/assets/js/3a1ed2bb.18ad5ad5.js create mode 100644 docs/assets/js/3b8c55ea.4ab0bf60.js delete mode 100644 docs/assets/js/3b8c55ea.d50f0d5a.js create mode 100644 docs/assets/js/3e4c86d4.0b3602b2.js delete mode 100644 docs/assets/js/3e4c86d4.eaafa28e.js create mode 100644 docs/assets/js/3fcb412e.54c127a8.js delete mode 100644 docs/assets/js/3fcb412e.d61d4ab6.js create mode 100644 docs/assets/js/422308df.b9cbb4dc.js delete mode 100644 docs/assets/js/422308df.c748cc2d.js delete mode 100644 docs/assets/js/4351fb58.2ba23a80.js create mode 100644 docs/assets/js/4351fb58.d28caec9.js delete mode 100644 docs/assets/js/44b2adf6.28ae2c3b.js create mode 100644 docs/assets/js/44b2adf6.95473760.js delete mode 100644 docs/assets/js/48ae5635.4f79be50.js create mode 100644 docs/assets/js/48ae5635.ae8b4c4e.js delete mode 100644 docs/assets/js/4972.e3352a90.js delete mode 100644 docs/assets/js/4d54d076.6a163bd0.js create mode 100644 docs/assets/js/4d54d076.d5641f32.js create mode 100644 docs/assets/js/4eac74de.cd66025d.js delete mode 100644 docs/assets/js/4eac74de.fb8596ee.js create mode 100644 docs/assets/js/4fa03c51.7f9609b5.js delete mode 100644 docs/assets/js/4fa03c51.ad054cf8.js delete mode 100644 docs/assets/js/4fb2362d.43d62e16.js create mode 100644 docs/assets/js/4fb2362d.5120e8b9.js create mode 100644 docs/assets/js/5281b7a2.981f96dc.js delete mode 100644 docs/assets/js/5281b7a2.ceaf1ffc.js delete mode 100644 docs/assets/js/5603335d.05cbde15.js create mode 100644 docs/assets/js/5603335d.b23ecd98.js create mode 100644 docs/assets/js/59e5a646.d59d85e0.js delete mode 100644 docs/assets/js/59e5a646.e9edd18a.js create mode 100644 docs/assets/js/5af9b662.48bb081f.js delete mode 100644 docs/assets/js/5af9b662.988a70e9.js delete mode 100644 docs/assets/js/5bc37772.1188e660.js create mode 100644 docs/assets/js/5bc37772.c2ae9680.js delete mode 100644 docs/assets/js/5c838b7d.8c56c538.js create mode 100644 docs/assets/js/5c838b7d.abeb9ef9.js create mode 100644 docs/assets/js/5e95c892.b00730d7.js create mode 100644 docs/assets/js/62c6dc45.beacabe7.js delete mode 100644 docs/assets/js/62c6dc45.d4fbe534.js delete mode 100644 docs/assets/js/6739d7ff.89c2e76b.js create mode 100644 docs/assets/js/6739d7ff.c14998ff.js delete mode 100644 docs/assets/js/6780.2f5c1e5a.js delete mode 100644 docs/assets/js/695a8bbb.23b6fade.js create mode 100644 docs/assets/js/695a8bbb.ab71b31c.js delete mode 100644 docs/assets/js/6af0c1ea.4be63f6e.js create mode 100644 docs/assets/js/6af0c1ea.e59808b7.js create mode 100644 docs/assets/js/6b8e46b3.1f13278c.js delete mode 100644 docs/assets/js/6b8e46b3.2a4f2d74.js delete mode 100644 docs/assets/js/6ec64a11.ac3c351f.js create mode 100644 docs/assets/js/6ec64a11.e804f073.js delete mode 100644 docs/assets/js/70b084fe.021d30e0.js create mode 100644 docs/assets/js/70b084fe.e3b3cc0e.js delete mode 100644 docs/assets/js/7196cdd1.5bf303c3.js create mode 100644 docs/assets/js/7196cdd1.e3825316.js create mode 100644 docs/assets/js/72e14192.52383938.js delete mode 100644 docs/assets/js/72e14192.5d76082f.js create mode 100644 docs/assets/js/72ffabc7.89379632.js delete mode 100644 docs/assets/js/72ffabc7.d08704ae.js create mode 100644 docs/assets/js/7b11c903.40de134e.js delete mode 100644 docs/assets/js/7b11c903.ce482ce3.js delete mode 100644 docs/assets/js/7c6883b5.468dab34.js create mode 100644 docs/assets/js/7c6883b5.a26ba92b.js delete mode 100644 docs/assets/js/7d415946.1d8d923e.js create mode 100644 docs/assets/js/7d415946.b8046362.js create mode 100644 docs/assets/js/7d6336d8.545b329a.js delete mode 100644 docs/assets/js/7d6336d8.d9e3c66f.js create mode 100644 docs/assets/js/85c70040.6420b355.js delete mode 100644 docs/assets/js/85c70040.e0419889.js create mode 100644 docs/assets/js/8c9fcf50.cf3bd3d7.js delete mode 100644 docs/assets/js/8c9fcf50.e1bd2694.js create mode 100644 docs/assets/js/8cd4fd18.5d94802b.js delete mode 100644 docs/assets/js/8cd4fd18.5dd67d55.js delete mode 100644 docs/assets/js/8eef7690.687f1101.js create mode 100644 docs/assets/js/8eef7690.ca5fd282.js delete mode 100644 docs/assets/js/8f41530a.3235cd00.js create mode 100644 docs/assets/js/8f41530a.d1d7746f.js create mode 100644 docs/assets/js/935f2afb.0a68307c.js delete mode 100644 docs/assets/js/935f2afb.da0a9203.js create mode 100644 docs/assets/js/93bf47d2.597826fd.js delete mode 100644 docs/assets/js/93bf47d2.cca23454.js delete mode 100644 docs/assets/js/974203ee.4618b9f3.js create mode 100644 docs/assets/js/974203ee.db23a97e.js delete mode 100644 docs/assets/js/9748995c.8c0b6d5e.js create mode 100644 docs/assets/js/9748995c.9c31807a.js create mode 100644 docs/assets/js/99ed3086.1ed71bcf.js delete mode 100644 docs/assets/js/99ed3086.694e142d.js delete mode 100644 docs/assets/js/9d55bf96.47c09e6a.js create mode 100644 docs/assets/js/9d55bf96.48d408b8.js create mode 100644 docs/assets/js/9dbb4f95.67a9bc2d.js delete mode 100644 docs/assets/js/9dbb4f95.ea996f10.js delete mode 100644 docs/assets/js/9e350ec0.513719f1.js create mode 100644 docs/assets/js/9e350ec0.5d832f0e.js delete mode 100644 docs/assets/js/9ff53b5b.5c60e5b7.js create mode 100644 docs/assets/js/9ff53b5b.7090781c.js delete mode 100644 docs/assets/js/a09c2993.479588b5.js create mode 100644 docs/assets/js/a09c2993.9909da7a.js create mode 100644 docs/assets/js/a683e47f.6b48266e.js delete mode 100644 docs/assets/js/a683e47f.b8f20d95.js delete mode 100644 docs/assets/js/a708fa78.2bb257f2.js create mode 100644 docs/assets/js/a708fa78.54aaa7fc.js create mode 100644 docs/assets/js/a7bd4aaa.45274bc2.js create mode 100644 docs/assets/js/a8f67d08.9df77a9f.js delete mode 100644 docs/assets/js/a8f67d08.d837a742.js create mode 100644 docs/assets/js/a932041a.2d3e796f.js delete mode 100644 docs/assets/js/a932041a.d5e014b0.js create mode 100644 docs/assets/js/a94703ab.5018fc8a.js create mode 100644 docs/assets/js/ae417a11.3d424f98.js delete mode 100644 docs/assets/js/ae417a11.d3ca84d8.js delete mode 100644 docs/assets/js/b0fc3de5.3454cfc2.js create mode 100644 docs/assets/js/b0fc3de5.be5ce799.js create mode 100644 docs/assets/js/b70ea2cb.1f9cdb37.js delete mode 100644 docs/assets/js/b70ea2cb.99ee2f04.js delete mode 100644 docs/assets/js/b7730d0d.1c52ffde.js create mode 100644 docs/assets/js/b7730d0d.88998729.js delete mode 100644 docs/assets/js/b7cd4035.0ab6a66d.js create mode 100644 docs/assets/js/b7cd4035.d3c04a53.js create mode 100644 docs/assets/js/b9421f89.292245b3.js delete mode 100644 docs/assets/js/b9421f89.bce75c8a.js delete mode 100644 docs/assets/js/bacc1ae0.816015a9.js create mode 100644 docs/assets/js/bacc1ae0.c11996b0.js create mode 100644 docs/assets/js/bbedbacb.734bd7d6.js delete mode 100644 docs/assets/js/bbedbacb.9fcac33b.js create mode 100644 docs/assets/js/bc344202.0b3ac2c6.js delete mode 100644 docs/assets/js/bc344202.a00f1fb9.js delete mode 100644 docs/assets/js/bc8dcae3.4c7ec3a0.js create mode 100644 docs/assets/js/bc8dcae3.deeb5da5.js create mode 100644 docs/assets/js/bdb5eb86.9d21e19a.js delete mode 100644 docs/assets/js/bdb5eb86.b95ff3d4.js delete mode 100644 docs/assets/js/bf5c5542.4f1330ce.js create mode 100644 docs/assets/js/bf5c5542.ec01ec49.js create mode 100644 docs/assets/js/bffae3e7.d211ec7b.js delete mode 100644 docs/assets/js/bffae3e7.d34bc0df.js create mode 100644 docs/assets/js/c108e81c.3dfa39c8.js delete mode 100644 docs/assets/js/c108e81c.619f3030.js delete mode 100644 docs/assets/js/c12dc9fd.1b6a252d.js create mode 100644 docs/assets/js/c12dc9fd.ade4b346.js delete mode 100644 docs/assets/js/c4f50fcb.b3a1918d.js create mode 100644 docs/assets/js/c4f50fcb.ddfb9faa.js create mode 100644 docs/assets/js/c66bbf8a.13446857.js delete mode 100644 docs/assets/js/c66bbf8a.1acc839f.js delete mode 100644 docs/assets/js/c698fe77.164c142f.js create mode 100644 docs/assets/js/c698fe77.a9373167.js create mode 100644 docs/assets/js/c73303db.0eee1cb1.js delete mode 100644 docs/assets/js/c73303db.be916204.js delete mode 100644 docs/assets/js/c853dc39.2fc0de50.js create mode 100644 docs/assets/js/c853dc39.861078cc.js delete mode 100644 docs/assets/js/c9ca4745.da4f0967.js create mode 100644 docs/assets/js/c9ca4745.e2a7d363.js delete mode 100644 docs/assets/js/d40dbec5.3ea65837.js create mode 100644 docs/assets/js/d40dbec5.8e7bd9d0.js delete mode 100644 docs/assets/js/d7561401.2cac3291.js create mode 100644 docs/assets/js/d7561401.72651373.js delete mode 100644 docs/assets/js/db59132a.6f50c1d0.js create mode 100644 docs/assets/js/db59132a.bdd9cb70.js create mode 100644 docs/assets/js/dbbf7db4.ad052b4c.js delete mode 100644 docs/assets/js/dbbf7db4.c7332918.js create mode 100644 docs/assets/js/dc9281b9.7ca1886c.js delete mode 100644 docs/assets/js/dc9281b9.8b8ee3c8.js delete mode 100644 docs/assets/js/dea0f9ea.313a6052.js create mode 100644 docs/assets/js/dea0f9ea.7a05a9de.js create mode 100644 docs/assets/js/e1b2cf59.5eb99ea6.js delete mode 100644 docs/assets/js/e1b2cf59.b8a8ffb4.js create mode 100644 docs/assets/js/e36340b6.4feb6f73.js delete mode 100644 docs/assets/js/e36340b6.8972753a.js create mode 100644 docs/assets/js/e3d8f98f.a2c52a4d.js delete mode 100644 docs/assets/js/e3d8f98f.c2802ab1.js create mode 100644 docs/assets/js/e7fdf6d9.94d9b31c.js delete mode 100644 docs/assets/js/e7fdf6d9.de866fbb.js delete mode 100644 docs/assets/js/ec0d5d9e.2c250436.js create mode 100644 docs/assets/js/ec0d5d9e.3d394cb4.js create mode 100644 docs/assets/js/ed8448fe.485bf575.js delete mode 100644 docs/assets/js/ed8448fe.b3589d7f.js create mode 100644 docs/assets/js/efdb11b6.0bcb2915.js delete mode 100644 docs/assets/js/efdb11b6.c5386572.js create mode 100644 docs/assets/js/f2ef54d0.06e099a0.js delete mode 100644 docs/assets/js/f2ef54d0.4af2136b.js delete mode 100644 docs/assets/js/fa2b770f.4d309065.js create mode 100644 docs/assets/js/fa2b770f.f4f734aa.js create mode 100644 docs/assets/js/faa9d310.5838e10c.js delete mode 100644 docs/assets/js/faa9d310.9de6aa31.js delete mode 100644 docs/assets/js/fc618254.c686b75c.js create mode 100644 docs/assets/js/fc618254.e65d5a68.js create mode 100644 docs/assets/js/fcff9033.00614336.js delete mode 100644 docs/assets/js/fcff9033.b18535a7.js delete mode 100644 docs/assets/js/fd1ae250.0fe36588.js create mode 100644 docs/assets/js/fd1ae250.8a9454eb.js delete mode 100644 docs/assets/js/main.3fdea3bd.js create mode 100644 docs/assets/js/main.424bf04c.js rename docs/assets/js/{main.3fdea3bd.js.LICENSE.txt => main.424bf04c.js.LICENSE.txt} (76%) delete mode 100644 docs/assets/js/runtime~main.3e75485d.js create mode 100644 docs/assets/js/runtime~main.7ab14693.js diff --git a/docs/404.html b/docs/404.html index 0abe07f26f..759953003a 100644 --- a/docs/404.html +++ b/docs/404.html @@ -1,22 +1,19 @@ - + - -Page Not Found | Eraser Docs + +Eraser Docs - - - + + + -
-
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

\ No newline at end of file diff --git a/docs/architecture.html b/docs/architecture.html index d8da84169f..d5f5d7fdc0 100644 --- a/docs/architecture.html +++ b/docs/architecture.html @@ -1,27 +1,30 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Skip to main content
Version: v1.3.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: v1.3.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/assets/css/styles.28354d54.css b/docs/assets/css/styles.28354d54.css deleted file mode 100644 index 34770da53a..0000000000 --- a/docs/assets/css/styles.28354d54.css +++ /dev/null @@ -1 +0,0 @@ -.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,.hash-link{-webkit-user-select:none}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}*,.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:transparent;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:rgba(0,0,0,.05);--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 rgba(0,0,0,.1);--ifm-global-shadow-md:0 5px 40px rgba(0,0,0,.2);--ifm-global-shadow-tl:0 12px 28px 0 rgba(0,0,0,.2),0 2px 4px 0 rgba(0,0,0,.1);--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:transparent;--ifm-table-stripe-background:rgba(0,0,0,.03);--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#2e8555;--ifm-color-primary-dark:#29784c;--ifm-color-primary-darker:#277148;--ifm-color-primary-darkest:#205d3b;--ifm-color-primary-light:#33925d;--ifm-color-primary-lighter:#359962;--ifm-color-primary-lightest:#3cad6e;--ifm-code-font-size:95%;--docusaurus-highlighted-code-line-bg:rgba(0,0,0,.1);--docusaurus-announcement-bar-height:auto;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-collapse-button-bg:transparent;--docusaurus-collapse-button-bg-hover:rgba(0,0,0,.1);--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:rgba(101,108,133,.8);--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 hsla(0,0%,100%,.5),0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 rgba(69,98,155,.12);--docsearch-primary-color:var(--ifm-color-primary);--docsearch-text-color:var(--ifm-font-color-base)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:transparent}html{-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base)}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid rgba(0,0,0,.1);border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_tbUL,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{list-style:none;padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:rgba(53,120,229,.15);--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:rgba(235,237,240,.15);--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:rgba(0,164,0,.15);--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:rgba(84,199,236,.15);--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:rgba(255,186,0,.15);--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:rgba(250,56,62,.15);--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{-webkit-text-decoration-color:var(--ifm-alert-border-color);text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:-webkit-any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs__link:any-link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:transparent;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;list-style:none;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor transparent;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_S0QG>:last-child,.collapsibleContent_i85q>:last-child,.footer__items{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{list-style:none;margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter);content:""}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:-webkit-sticky;position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:hsla(0,0%,100%,.1);--ifm-navbar-search-input-placeholder-color:hsla(0,0%,100%,.5);color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:hsla(0,0%,100%,.05);--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:rgba(0,0,0,.6);right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid transparent;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:hsla(0,0%,100%,.05);--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:hsla(0,0%,100%,.1);--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:hsla(0,0%,100%,.07);--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec;--docsearch-text-color:#f5f6f7;--docsearch-container-background:rgba(9,10,17,.8);--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 rgba(3,4,9,.3);--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73,76,106,.5),0 -4px 8px 0 rgba(0,0,0,.2);--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}[data-theme=dark]{--ifm-color-primary:#25c2a0;--ifm-color-primary-dark:#21af90;--ifm-color-primary-darker:#1fa588;--ifm-color-primary-darkest:#1a8870;--ifm-color-primary-light:#29d5b0;--ifm-color-primary-lighter:#32d8b4;--ifm-color-primary-lightest:#4fddbf;--docusaurus-highlighted-code-line-bg:rgba(0,0,0,.3)}.header-github-link:hover{opacity:.6}.header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;content:"";display:flex;height:24px;width:24px}html[data-theme=dark] .header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#__docusaurus-base-url-issue-banner-container,.themedImage_ToTc,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.DocSearch-Container a,.tag_zVej:hover{text-decoration:none}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedImage--dark_i4oU,[data-theme=light] .themedImage--light_HNdA,html:not([data-theme]) .themedComponent--light_NU7w{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color)}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:-webkit-sticky;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);user-select:none}.hash-link:before{content:"#"}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:-webkit-sticky;position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;list-style:none;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:transparent transparent transparent var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.containsTaskList_mC6p{list-style:none}.img_ev3q{height:auto}.admonition_LlT9{margin-bottom:1em}.admonitionHeading_tbUL{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.3rem}.admonitionHeading_tbUL code{text-transform:none}.admonitionIcon_kALy{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_kALy svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.searchQueryInput_u2C7,.searchVersionInput_m0Ui{background:var(--docsearch-searchbox-focus-background);border:2px solid var(--ifm-toc-border-color);border-radius:var(--ifm-global-radius);color:var(--docsearch-text-color);font:var(--ifm-font-size-base) var(--ifm-font-family-base);margin-bottom:.5rem;padding:.8rem;transition:border var(--ifm-transition-fast) ease;width:100%}.searchQueryInput_u2C7:focus,.searchVersionInput_m0Ui:focus{border-color:var(--docsearch-primary-color);outline:0}.searchQueryInput_u2C7::placeholder{color:var(--docsearch-muted-color)}.searchResultsColumn_JPFH{font-size:.9rem;font-weight:700}.algoliaLogo_rT1R{max-width:150px}.algoliaLogoPathFill_WdUC{fill:var(--ifm-font-color-base)}.searchResultItem_Tv2o{border-bottom:1px solid var(--ifm-toc-border-color);padding:1rem 0}.searchResultItemHeading_KbCB{font-weight:400;margin-bottom:0}.searchResultItemPath_lhe1{--ifm-breadcrumb-separator-size-multiplier:1;color:var(--ifm-color-content-secondary);font-size:.8rem}.searchResultItemSummary_AEaO{font-style:italic;margin:.5rem 0 0}.loadingSpinner_XVxU{animation:1s linear infinite a;border:.4em solid #eee;border-radius:50%;border-top:.4em solid var(--ifm-color-primary);height:3rem;margin:0 auto;width:3rem}@keyframes a{to{transform:rotate(1turn)}}.loader_vvXV{margin-top:2rem}.search-result-match{background:rgba(255,215,142,.25);color:var(--docsearch-hit-color);padding:.09em 0}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:hsla(0,0%,100%,.05);--docusaurus-collapse-button-bg-hover:hsla(0,0%,100%,.1)}.collapseSidebarButton_PEFL{display:none;margin:0}.docSidebarContainer_b6E3,.sidebarLogo_isFc{display:none}.docMainContainer_gTbr,.docPage__5DB{display:flex;width:100%}.docPage__5DB{flex:1 0}.docsWrapper_BCFX{display:flex;flex:1 0 auto}.DocSearch-Button,.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Button{background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;font-weight:500;height:36px;justify-content:space-between;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:0}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Hit-Tree,.DocSearch-Hit-action,.DocSearch-Hit-icon,.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Input,.DocSearch-Link{-webkit-appearance:none;font:inherit}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch--active{overflow:hidden!important}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:0 0;border:0;color:var(--docsearch-text-color);flex:1;font-size:1.2em;height:100%;outline:0;padding:0 0 0 8px;width:80%}.DocSearch-Hit-action-button,.DocSearch-Reset{-webkit-appearance:none;border:0;cursor:pointer}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Cancel,.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator,.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset{animation:.1s ease-in forwards b;appearance:none;background:none;border-radius:50%;color:var(--docsearch-icon-color);padding:2px;right:0}.DocSearch-Help,.DocSearch-HitsFooter,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Reset:focus{outline:0}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:0 0}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}.DocSearch-Hit--deleting{opacity:0;transition:.25s linear}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:.25s linear .25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:-webkit-sticky;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border-radius:50%;color:inherit;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:background-color .1s ease-in}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:0;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}@keyframes b{0%{opacity:0}to{opacity:1}}.DocSearch-Button{margin:0;transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.DocSearch-Container{z-index:calc(var(--ifm-z-index-fixed) + 1)}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_m80_{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.searchBox_ZlJk{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn{max-width:75%!important}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:-webkit-sticky;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_BlDH,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_m80_:focus,.expandButton_m80_:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_m80_{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_BlDH{transform:rotate(180deg)}.docSidebarContainer_b6E3{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_b3ry{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_Xe31{height:100%;max-height:100vh;position:-webkit-sticky;position:sticky;top:0}.docMainContainer_gTbr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_Uz_u{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_czyv{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.searchBox_ZlJk{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media only screen and (max-width:996px){.searchQueryColumn_RTkw,.searchResultsColumn_JPFH{max-width:60%!important}.searchLogoColumn_rJIA,.searchVersionColumn_ypXd{max-width:40%!important}.searchLogoColumn_rJIA{padding-left:0!important}}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder,.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%;max-height:calc(var(--docsearch-vh,1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Cancel{-webkit-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:0;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media screen and (max-width:576px){.searchQueryColumn_RTkw{max-width:100%!important}.searchVersionColumn_ypXd{max-width:100%!important;padding-left:var(--ifm-spacing-horizontal)!important}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width);animation:none;-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0}.DocSearch-Hit--deleting,.DocSearch-Hit--favoriting{transition:none}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:rgba(0,0,0,.2);transition:none}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file diff --git a/docs/assets/css/styles.e36959ff.css b/docs/assets/css/styles.e36959ff.css new file mode 100644 index 0000000000..c3e5a9eada --- /dev/null +++ b/docs/assets/css/styles.e36959ff.css @@ -0,0 +1 @@ +.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,.hash-link{-webkit-user-select:none}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}*,.DocSearch-Container,.DocSearch-Container *{box-sizing:border-box}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#2e8555;--ifm-color-primary-dark:#29784c;--ifm-color-primary-darker:#277148;--ifm-color-primary-darkest:#205d3b;--ifm-color-primary-light:#33925d;--ifm-color-primary-lighter:#359962;--ifm-color-primary-lightest:#3cad6e;--ifm-code-font-size:95%;--docusaurus-highlighted-code-line-bg:#0000001a;--docusaurus-announcement-bar-height:auto;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docsearch-primary-color:#5468ff;--docsearch-text-color:#1c1e21;--docsearch-spacing:12px;--docsearch-icon-stroke-width:1.4;--docsearch-highlight-color:var(--docsearch-primary-color);--docsearch-muted-color:#969faf;--docsearch-container-background:#656c85cc;--docsearch-logo-color:#5468ff;--docsearch-modal-width:560px;--docsearch-modal-height:600px;--docsearch-modal-background:#f5f6f7;--docsearch-modal-shadow:inset 1px 1px 0 0 #ffffff80,0 3px 8px 0 #555a64;--docsearch-searchbox-height:56px;--docsearch-searchbox-background:#ebedf0;--docsearch-searchbox-focus-background:#fff;--docsearch-searchbox-shadow:inset 0 0 0 2px var(--docsearch-primary-color);--docsearch-hit-height:56px;--docsearch-hit-color:#444950;--docsearch-hit-active-color:#fff;--docsearch-hit-background:#fff;--docsearch-hit-shadow:0 1px 3px 0 #d4d9e1;--docsearch-key-gradient:linear-gradient(-225deg,#d5dbe4,#f8f8f8);--docsearch-key-shadow:inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px #1e235a66;--docsearch-footer-height:44px;--docsearch-footer-background:#fff;--docsearch-footer-shadow:0 -1px 0 0 #e0e3e8,0 -3px 6px 0 #45629b1f;--docsearch-primary-color:var(--ifm-color-primary);--docsearch-text-color:var(--ifm-font-color-base)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_Gvgb,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{list-style:none;padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;list-style:none;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_BuS1>:last-child,.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p:last-child,.footer__items{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{list-style:none;margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;content:"";filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec;--docsearch-text-color:#f5f6f7;--docsearch-container-background:#090a11cc;--docsearch-modal-background:#15172a;--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40,0 3px 8px 0 #000309;--docsearch-searchbox-background:#090a11;--docsearch-searchbox-focus-background:#000;--docsearch-hit-color:#bec3c9;--docsearch-hit-shadow:none;--docsearch-hit-background:#090a11;--docsearch-key-gradient:linear-gradient(-26.5deg,#565872,#31355b);--docsearch-key-shadow:inset 0 -2px 0 0 #282d55,inset 0 0 1px 1px #51577d,0 2px 2px 0 #0304094d;--docsearch-footer-background:#1e2136;--docsearch-footer-shadow:inset 0 1px 0 0 #494c6a80,0 -4px 8px 0 #0003;--docsearch-logo-color:#fff;--docsearch-muted-color:#7f8497}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}[data-theme=dark]{--ifm-color-primary:#25c2a0;--ifm-color-primary-dark:#21af90;--ifm-color-primary-darker:#1fa588;--ifm-color-primary-darkest:#1a8870;--ifm-color-primary-light:#29d5b0;--ifm-color-primary-lighter:#32d8b4;--ifm-color-primary-lightest:#4fddbf;--docusaurus-highlighted-code-line-bg:#0000004d}.header-github-link:hover{opacity:.6}.header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;content:"";display:flex;height:24px;width:24px}html[data-theme=dark] .header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}#__docusaurus-base-url-issue-banner-container,.themedComponent_mlkZ,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.DocSearch-Container a,.tag_zVej:hover{text-decoration:none}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedComponent--dark_xIcU,[data-theme=light] .themedComponent--light_NVdE,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}.iconExternalLink_nPIU{margin-left:.3rem}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}@supports selector(:has(*)){.navbarSearchContainer_Bca1:not(:has(>*)){display:none}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);user-select:none}.hash-link:before{content:"#"}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color)}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;list-style:none;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.containsTaskList_mC6p{list-style:none}.img_ev3q{height:auto}.admonition_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Rf37 svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.searchQueryInput_u2C7,.searchVersionInput_m0Ui{background:var(--docsearch-searchbox-focus-background);border:2px solid var(--ifm-toc-border-color);border-radius:var(--ifm-global-radius);color:var(--docsearch-text-color);font:var(--ifm-font-size-base) var(--ifm-font-family-base);margin-bottom:.5rem;padding:.8rem;transition:border var(--ifm-transition-fast) ease;width:100%}.searchQueryInput_u2C7:focus,.searchVersionInput_m0Ui:focus{border-color:var(--docsearch-primary-color);outline:0}.searchQueryInput_u2C7::placeholder{color:var(--docsearch-muted-color)}.searchResultsColumn_JPFH{font-size:.9rem;font-weight:700}.algoliaLogo_rT1R{max-width:150px}.algoliaLogoPathFill_WdUC{fill:var(--ifm-font-color-base)}.searchResultItem_Tv2o{border-bottom:1px solid var(--ifm-toc-border-color);padding:1rem 0}.searchResultItemHeading_KbCB{font-weight:400;margin-bottom:0}.searchResultItemPath_lhe1{--ifm-breadcrumb-separator-size-multiplier:1;color:var(--ifm-color-content-secondary);font-size:.8rem}.searchResultItemSummary_AEaO{font-style:italic;margin:.5rem 0 0}.loadingSpinner_XVxU{animation:1s linear infinite a;border:.4em solid #eee;border-radius:50%;border-top:.4em solid var(--ifm-color-primary);height:3rem;margin:0 auto;width:3rem}@keyframes a{to{transform:rotate(1turn)}}.loader_vvXV{margin-top:2rem}.search-result-match{background:#ffd78e40;color:var(--docsearch-hit-color);padding:.09em 0}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.docSidebarContainer_YfHR,.sidebarLogo_isFc{display:none}.docMainContainer_TBSr,.docRoot_UBD9{display:flex;width:100%}.docsWrapper_hBAB{display:flex;flex:1 0 auto}.DocSearch-Button,.DocSearch-Button-Container{align-items:center;display:flex}.DocSearch-Button{background:var(--docsearch-searchbox-background);border:0;border-radius:40px;color:var(--docsearch-muted-color);cursor:pointer;font-weight:500;height:36px;justify-content:space-between;padding:0 8px;-webkit-user-select:none;user-select:none}.DocSearch-Button:active,.DocSearch-Button:focus,.DocSearch-Button:hover{background:var(--docsearch-searchbox-focus-background);box-shadow:var(--docsearch-searchbox-shadow);color:var(--docsearch-text-color);outline:0}.DocSearch-Search-Icon{stroke-width:1.6}.DocSearch-Hit-Tree,.DocSearch-Hit-action,.DocSearch-Hit-icon,.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width)}.DocSearch-Button .DocSearch-Search-Icon{color:var(--docsearch-text-color)}.DocSearch-Button-Placeholder{font-size:1rem;padding:0 12px 0 6px}.DocSearch-Input,.DocSearch-Link{-webkit-appearance:none;font:inherit}.DocSearch-Button-Keys{display:flex;min-width:calc(40px + .8em)}.DocSearch-Button-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:3px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 2px;position:relative;top:-1px;width:20px}.DocSearch--active{overflow:hidden!important}.DocSearch-Container{background-color:var(--docsearch-container-background);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}.DocSearch-Link{appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;margin:0;padding:0}.DocSearch-Modal{background:var(--docsearch-modal-background);border-radius:6px;box-shadow:var(--docsearch-modal-shadow);flex-direction:column;margin:60px auto auto;max-width:var(--docsearch-modal-width);position:relative}.DocSearch-SearchBar{display:flex;padding:var(--docsearch-spacing) var(--docsearch-spacing) 0}.DocSearch-Form{align-items:center;background:var(--docsearch-searchbox-focus-background);border-radius:4px;box-shadow:var(--docsearch-searchbox-shadow);display:flex;height:var(--docsearch-searchbox-height);margin:0;padding:0 var(--docsearch-spacing);position:relative;width:100%}.DocSearch-Input{appearance:none;background:#0000;border:0;color:var(--docsearch-text-color);flex:1;font-size:1.2em;height:100%;outline:0;padding:0 0 0 8px;width:80%}.DocSearch-Hit-action-button,.DocSearch-Reset{-webkit-appearance:none;border:0;cursor:pointer}.DocSearch-Input::placeholder{color:var(--docsearch-muted-color);opacity:1}.DocSearch-Input::-webkit-search-cancel-button,.DocSearch-Input::-webkit-search-decoration,.DocSearch-Input::-webkit-search-results-button,.DocSearch-Input::-webkit-search-results-decoration{display:none}.DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{margin:0;padding:0}.DocSearch-Container--Stalled .DocSearch-LoadingIndicator,.DocSearch-MagnifierLabel,.DocSearch-Reset{align-items:center;color:var(--docsearch-highlight-color);display:flex;justify-content:center}.DocSearch-Cancel,.DocSearch-Container--Stalled .DocSearch-MagnifierLabel,.DocSearch-LoadingIndicator,.DocSearch-Reset[hidden]{display:none}.DocSearch-Reset{animation:.1s ease-in forwards b;appearance:none;background:none;border-radius:50%;color:var(--docsearch-icon-color);padding:2px;right:0}.DocSearch-Help,.DocSearch-HitsFooter,.DocSearch-Label{color:var(--docsearch-muted-color)}.DocSearch-Reset:hover{color:var(--docsearch-highlight-color)}.DocSearch-LoadingIndicator svg,.DocSearch-MagnifierLabel svg{height:24px;width:24px}.DocSearch-Dropdown{max-height:calc(var(--docsearch-modal-height) - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height));min-height:var(--docsearch-spacing);overflow-y:auto;overflow-y:overlay;padding:0 var(--docsearch-spacing);scrollbar-color:var(--docsearch-muted-color) var(--docsearch-modal-background);scrollbar-width:thin}.DocSearch-Dropdown::-webkit-scrollbar{width:12px}.DocSearch-Dropdown::-webkit-scrollbar-track{background:#0000}.DocSearch-Dropdown::-webkit-scrollbar-thumb{background-color:var(--docsearch-muted-color);border:3px solid var(--docsearch-modal-background);border-radius:20px}.DocSearch-Dropdown ul{list-style:none;margin:0;padding:0}.DocSearch-Label{font-size:.75em;line-height:1.6em}.DocSearch-Help{font-size:.9em;margin:0;-webkit-user-select:none;user-select:none}.DocSearch-Title{font-size:1.2em}.DocSearch-Logo a{display:flex}.DocSearch-Logo svg{color:var(--docsearch-logo-color);margin-left:8px}.DocSearch-Hits:last-of-type{margin-bottom:24px}.DocSearch-Hits mark{background:none;color:var(--docsearch-highlight-color)}.DocSearch-HitsFooter{display:flex;font-size:.85em;justify-content:center;margin-bottom:var(--docsearch-spacing);padding:var(--docsearch-spacing)}.DocSearch-HitsFooter a{border-bottom:1px solid;color:inherit}.DocSearch-Hit{border-radius:4px;display:flex;padding-bottom:4px;position:relative}.DocSearch-Hit--deleting{opacity:0;transition:.25s linear}.DocSearch-Hit--favoriting{transform:scale(0);transform-origin:top center;transition:.25s linear .25s}.DocSearch-Hit a{background:var(--docsearch-hit-background);border-radius:4px;box-shadow:var(--docsearch-hit-shadow);display:block;padding-left:var(--docsearch-spacing);width:100%}.DocSearch-Hit-source{background:var(--docsearch-modal-background);color:var(--docsearch-highlight-color);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:8px 4px 0;position:sticky;top:0;z-index:10}.DocSearch-Hit-Tree{color:var(--docsearch-muted-color);height:var(--docsearch-hit-height);opacity:.5;width:24px}.DocSearch-Hit[aria-selected=true] a{background-color:var(--docsearch-highlight-color)}.DocSearch-Hit[aria-selected=true] mark{text-decoration:underline}.DocSearch-Hit-Container{align-items:center;color:var(--docsearch-hit-color);display:flex;flex-direction:row;height:var(--docsearch-hit-height);padding:0 var(--docsearch-spacing) 0 0}.DocSearch-Hit-icon{height:20px;width:20px}.DocSearch-Hit-action,.DocSearch-Hit-icon{color:var(--docsearch-muted-color)}.DocSearch-Hit-action{align-items:center;display:flex;height:22px;width:22px}.DocSearch-Hit-action svg{display:block;height:18px;width:18px}.DocSearch-Hit-action+.DocSearch-Hit-action{margin-left:6px}.DocSearch-Hit-action-button{appearance:none;background:none;border-radius:50%;color:inherit;padding:2px}svg.DocSearch-Hit-Select-Icon{display:none}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Select-Icon{display:block}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:background-color .1s ease-in}.DocSearch-Hit-action-button:focus path,.DocSearch-Hit-action-button:hover path{fill:#fff}.DocSearch-Hit-content-wrapper{display:flex;flex:1 1 auto;flex-direction:column;font-weight:500;justify-content:center;line-height:1.2em;margin:0 8px;overflow-x:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:80%}.DocSearch-Hit-title{font-size:.9em}.DocSearch-Hit-path{color:var(--docsearch-muted-color);font-size:.75em}.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-Tree,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-action,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-icon,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-path,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-text,.DocSearch-Hit[aria-selected=true] .DocSearch-Hit-title,.DocSearch-Hit[aria-selected=true] mark{color:var(--docsearch-hit-active-color)!important}.DocSearch-ErrorScreen,.DocSearch-NoResults,.DocSearch-StartScreen{font-size:.9em;margin:0 auto;padding:36px 0;text-align:center;width:80%}.DocSearch-Screen-Icon{color:var(--docsearch-muted-color);padding-bottom:12px}.DocSearch-NoResults-Prefill-List{display:inline-block;padding-bottom:24px;text-align:left}.DocSearch-NoResults-Prefill-List ul{display:inline-block;padding:8px 0 0}.DocSearch-NoResults-Prefill-List li{list-style-position:inside;list-style-type:"» "}.DocSearch-Prefill{-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:1em;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;font-size:1em;font-weight:700;padding:0}.DocSearch-Prefill:focus,.DocSearch-Prefill:hover{outline:0;text-decoration:underline}.DocSearch-Footer{align-items:center;background:var(--docsearch-footer-background);border-radius:0 0 8px 8px;box-shadow:var(--docsearch-footer-shadow);display:flex;flex-direction:row-reverse;flex-shrink:0;height:var(--docsearch-footer-height);justify-content:space-between;padding:0 var(--docsearch-spacing);position:relative;-webkit-user-select:none;user-select:none;width:100%;z-index:300}.DocSearch-Commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}.DocSearch-Commands li{align-items:center;display:flex}.DocSearch-Commands li:not(:last-of-type){margin-right:.8em}.DocSearch-Commands-Key{align-items:center;background:var(--docsearch-key-gradient);border:0;border-radius:2px;box-shadow:var(--docsearch-key-shadow);color:var(--docsearch-muted-color);display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;width:20px}@keyframes b{0%{opacity:0}to{opacity:1}}.DocSearch-Button{margin:0;transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.DocSearch-Container{z-index:calc(var(--ifm-z-index-fixed) + 1)}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_TmdG{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}.docItemCol_VOVn{max-width:75%!important}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_i1dp,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_TmdG:focus,.expandButton_TmdG:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_TmdG{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_i1dp{transform:rotate(180deg)}.docSidebarContainer_YfHR{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_DPk8{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_aRkj{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_TBSr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_lQrH{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_JWYK{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.navbarSearchContainer_Bca1{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media only screen and (max-width:996px){.searchQueryColumn_RTkw,.searchResultsColumn_JPFH{max-width:60%!important}.searchLogoColumn_rJIA,.searchVersionColumn_ypXd{max-width:40%!important}.searchLogoColumn_rJIA{padding-left:0!important}}@media (max-width:768px){.DocSearch-Button-Keys,.DocSearch-Button-Placeholder,.DocSearch-Commands,.DocSearch-Hit-Tree{display:none}:root{--docsearch-spacing:10px;--docsearch-footer-height:40px}.DocSearch-Dropdown{height:100%;max-height:calc(var(--docsearch-vh,1vh)*100 - var(--docsearch-searchbox-height) - var(--docsearch-spacing) - var(--docsearch-footer-height))}.DocSearch-Container{height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);position:absolute}.DocSearch-Footer{border-radius:0;bottom:0;position:absolute}.DocSearch-Hit-content-wrapper{display:flex;position:relative;width:80%}.DocSearch-Modal{border-radius:0;box-shadow:none;height:100vh;height:-webkit-fill-available;height:calc(var(--docsearch-vh,1vh)*100);margin:0;max-width:100%;width:100%}.DocSearch-Cancel{-webkit-appearance:none;appearance:none;background:none;border:0;color:var(--docsearch-highlight-color);cursor:pointer;display:inline-block;flex:none;font:inherit;font-size:1em;font-weight:500;margin-left:var(--docsearch-spacing);outline:0;overflow:hidden;padding:0;-webkit-user-select:none;user-select:none;white-space:nowrap}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media screen and (max-width:576px){.searchQueryColumn_RTkw{max-width:100%!important}.searchVersionColumn_ypXd{max-width:100%!important;padding-left:var(--ifm-spacing-horizontal)!important}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media screen and (prefers-reduced-motion:reduce){.DocSearch-Reset{stroke-width:var(--docsearch-icon-stroke-width);animation:none;-webkit-appearance:none;appearance:none;background:none;border:0;border-radius:50%;color:var(--docsearch-icon-color);cursor:pointer;right:0}.DocSearch-Hit--deleting,.DocSearch-Hit--favoriting{transition:none}.DocSearch-Hit-action-button:focus,.DocSearch-Hit-action-button:hover{background:#0003;transition:none}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file diff --git a/docs/assets/js/0390b328.2bf1bb4b.js b/docs/assets/js/0390b328.2bf1bb4b.js deleted file mode 100644 index 2da12025cf..0000000000 --- a/docs/assets/js/0390b328.2bf1bb4b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7868],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,c(c({ref:t},p),{},{components:n})):r.createElement(f,c({ref:t},p))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var l=2;l{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const o={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"version-v0.5.x/custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v0.5.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v0.5.x/custom-scanner",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v0.5.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v0.5.x/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],p={toc:l};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,a.kt)("p",null,"To create a custom scanner for non-compliant images, use the following ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser-scanner-template/"},"template"),"."),(0,a.kt)("p",null,"In order to customize your scanner, start by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},"NewImageProvider()"),". The ImageProvider interface can be found can be found ",(0,a.kt)("a",{parentName:"p",href:"../../pkg/scanners/template/scanner_template.go"},"here"),". "),(0,a.kt)("p",null,"The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,a.kt)("inlineCode",{parentName:"p"},"ReceiveImages()")," function. Process these images with your customized scanner and threshold, and use ",(0,a.kt)("inlineCode",{parentName:"p"},"SendImages()")," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,a.kt)("inlineCode",{parentName:"p"},"Finish()"),"."),(0,a.kt)("p",null,"When complete, provide your custom scanner image to Eraser in deployment."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/0390b328.50c3d7e8.js b/docs/assets/js/0390b328.50c3d7e8.js new file mode 100644 index 0000000000..0875e838b9 --- /dev/null +++ b/docs/assets/js/0390b328.50c3d7e8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7868],{5340:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var r=t(5893),s=t(1151);const o={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v0.5.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v0.5.x/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v0.5.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v0.5.x/trivy"}},i={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsxs)(n.p,{children:["To create a custom scanner for non-compliant images, use the following ",(0,r.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser-scanner-template/",children:"template"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In order to customize your scanner, start by creating a ",(0,r.jsx)(n.code,{children:"NewImageProvider()"}),". The ImageProvider interface can be found can be found ",(0,r.jsx)(n.a,{href:"../../pkg/scanners/template/scanner_template.go",children:"here"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,r.jsx)(n.code,{children:"ReceiveImages()"})," function. Process these images with your customized scanner and threshold, and use ",(0,r.jsx)(n.code,{children:"SendImages()"})," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,r.jsx)(n.code,{children:"Finish()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"When complete, provide your custom scanner image to Eraser in deployment."})]})}function u(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const s={},o=r.createContext(s);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/0480b142.32575a54.js b/docs/assets/js/0480b142.32575a54.js deleted file mode 100644 index 8bdbc646f5..0000000000 --- a/docs/assets/js/0480b142.32575a54.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[836],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),b=a,g=f["".concat(s,".").concat(b)]||f[b]||p[b]||i;return r?n.createElement(g,o(o({ref:t},u),{},{components:r})):n.createElement(g,o({ref:t},u))}));function b(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/docs/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/next/faq",draft:!1,tags:[],version:"current",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/next/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/next/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,a.kt)("p",null,"Eraser currently targets ",(0,a.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,a.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,a.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"configmap"),"."),(0,a.kt)("h2",{id:"how-is-eraser-different-from-kubernetes-garbage-collection"},"How is Eraser different from Kubernetes garbage collection?"),(0,a.kt)("p",null,"The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/"},"Kubernetes documentation"),", and configuration options can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/"},"Kubelet documentation"),". "),(0,a.kt)("p",null,"There are a couple core benefits to using Eraser for image cleanup:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Eraser can be configured to use image vulnerability data when making determinations on image removal"),(0,a.kt)("li",{parentName:"ul"},"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/0480b142.652e6bd1.js b/docs/assets/js/0480b142.652e6bd1.js new file mode 100644 index 0000000000..c79b013e76 --- /dev/null +++ b/docs/assets/js/0480b142.652e6bd1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[836],{8976:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var i=t(5893),r=t(1151);const a={title:"FAQ"},s=void 0,o={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/docs/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/next/faq",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/next/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/next/contributing"}},l={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,i.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"configmap"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"how-is-eraser-different-from-kubernetes-garbage-collection",children:"How is Eraser different from Kubernetes garbage collection?"}),"\n",(0,i.jsxs)(n.p,{children:["The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/",children:"Kubernetes documentation"}),", and configuration options can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/",children:"Kubelet documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There are a couple core benefits to using Eraser for image cleanup:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Eraser can be configured to use image vulnerability data when making determinations on image removal"}),"\n",(0,i.jsx)(n.li,{children:"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>o,a:()=>s});var i=t(7294);const r={},a=i.createContext(r);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/07e6d80c.5396be34.js b/docs/assets/js/07e6d80c.5396be34.js new file mode 100644 index 0000000000..42c9184726 --- /dev/null +++ b/docs/assets/js/07e6d80c.5396be34.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3939],{6429:(e,s,i)=>{i.r(s),i.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var r=i(5893),n=i(1151);const t={title:"Exclusion"},o=void 0,a={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.2.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v1.2.x/exclusion",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v1.2.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v1.2.x/customization"}},c={},l=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function d(e){const s={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,n.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,r.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,r.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,r.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,r.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,r.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,r.jsxs)(s.p,{children:["Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,r.jsx)(s.code,{children:"include"})," or ",(0,r.jsx)(s.code,{children:"exclude"})," from the cleanup process using the configmap. For more information, see the section on ",(0,r.jsx)(s.a,{href:"https://eraser-dev.github.io/eraser/docs/customization",children:"customization"}),"."]})]})}function u(e={}){const{wrapper:s}={...(0,n.a)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,s,i)=>{i.d(s,{Z:()=>a,a:()=>o});var r=i(7294);const n={},t=r.createContext(n);function o(e){const s=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/07e6d80c.53b2fbd7.js b/docs/assets/js/07e6d80c.53b2fbd7.js deleted file mode 100644 index 294ddbc612..0000000000 --- a/docs/assets/js/07e6d80c.53b2fbd7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3939],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=n.createContext({}),c=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},p=function(e){var r=c(e.components);return n.createElement(l.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(t),m=i,f=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?n.createElement(f,a(a({ref:r},p),{},{components:t})):n.createElement(f,a({ref:r},p))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var s={};for(var l in r)hasOwnProperty.call(r,l)&&(s[l]=r[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var c=2;c{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var n=t(7462),i=(t(7294),t(3905));const o={title:"Exclusion"},a=void 0,s={unversionedId:"exclusion",id:"version-v1.2.x/exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.2.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v1.2.x/exclusion",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v1.2.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v1.2.x/customization"}},l={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],p={toc:c};function u(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the configmap. For more information, see the section on ",(0,i.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization"},"customization"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/096837f0.771b8b12.js b/docs/assets/js/096837f0.771b8b12.js deleted file mode 100644 index 96162c3bcc..0000000000 --- a/docs/assets/js/096837f0.771b8b12.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6013],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"version-v1.1.x/manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.1.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v1.1.x/manual-removal",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v1.1.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v1.1.x/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.1.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v1.1.x/manual-removal",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v1.1.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v1.1.x/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/0d9a188d.1186d693.js b/docs/assets/js/0d9a188d.1186d693.js deleted file mode 100644 index 9ecd8a3f82..0000000000 --- a/docs/assets/js/0d9a188d.1186d693.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1865],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(r),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"version-v0.5.x/contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v0.5.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v0.5.x/contributing",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v0.5.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v0.5.x/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/0d9a188d.65d8092e.js b/docs/assets/js/0d9a188d.65d8092e.js new file mode 100644 index 0000000000..f8c4bcd983 --- /dev/null +++ b/docs/assets/js/0d9a188d.65d8092e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1865],{3582:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v0.5.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v0.5.x/contributing",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v0.5.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v0.5.x/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/0fb10398.6b984536.js b/docs/assets/js/0fb10398.6b984536.js new file mode 100644 index 0000000000..4d1b7ed9ad --- /dev/null +++ b/docs/assets/js/0fb10398.6b984536.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4781],{8457:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.2.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v1.2.x/setup",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/v1.2.x/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/v1.2.x/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/0fb10398.a6ee55bc.js b/docs/assets/js/0fb10398.a6ee55bc.js deleted file mode 100644 index 301cad93a6..0000000000 --- a/docs/assets/js/0fb10398.a6ee55bc.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4781],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"version-v1.2.x/setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.2.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v1.2.x/setup",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/v1.2.x/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/v1.2.x/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-remover"))),(0,r.kt)("p",null,"Builds the docker image for eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-remover"))),(0,r.kt)("p",null,"Builds the docker image for the eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/101be56a.8ca0113a.js b/docs/assets/js/101be56a.8ca0113a.js deleted file mode 100644 index 8b0d320499..0000000000 --- a/docs/assets/js/101be56a.8ca0113a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7029],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,i(i({ref:n},p),{},{components:t})):a.createElement(k,i({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,i=new Array(l);i[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var c=2;c{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},i=void 0,o={unversionedId:"quick-start",id:"version-v1.2.x/quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.2.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v1.2.x/quick-start",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v1.2.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v1.2.x/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/v1.2.x/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat < 45m v1.24.0\nkind-worker2 Ready 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.scheduling.repeatInterval")," setting in the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.enabled")," value to ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," using the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". In this case, each collector pod will hold 2 containers: collector and remover.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/101be56a.d26e4b44.js b/docs/assets/js/101be56a.d26e4b44.js new file mode 100644 index 0000000000..e5c51a46eb --- /dev/null +++ b/docs/assets/js/101be56a.d26e4b44.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7029],{7700:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var s=a(5893),t=a(1151);const r={title:"Quick Start"},i=void 0,l={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.2.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v1.2.x/quick-start",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v1.2.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v1.2.x/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,s.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,s.jsxs)(n.p,{children:["After following the ",(0,s.jsx)(n.a,{href:"/eraser/docs/v1.2.x/installation",children:"install instructions"}),", we'll apply a demo ",(0,s.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,s.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,s.jsxs)(n.p,{children:["First, apply the ",(0,s.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"cat < 45m v1.24.0\nkind-worker2 Ready 44m v1.24.0\n"})}),"\n",(0,s.jsxs)(n.p,{children:["List the images then filter for ",(0,s.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,s.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,s.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,s.jsx)(n.code,{children:"manager.scheduling.repeatInterval"})," setting in the ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". The default interval is 24 hours (",(0,s.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,s.jsx)(n.p,{children:"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,s.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,s.jsx)(n.code,{children:"components.scanner.enabled"})," value to ",(0,s.jsx)(n.code,{children:"false"})," using the ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". In this case, each collector pod will hold 2 containers: collector and remover."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>l,a:()=>i});var s=a(7294);const t={},r=s.createContext(t);function i(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/11d58a17.c673924e.js b/docs/assets/js/11d58a17.c673924e.js new file mode 100644 index 0000000000..1c85e2cbed --- /dev/null +++ b/docs/assets/js/11d58a17.c673924e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[154],{9138:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>f,frontMatter:()=>d,metadata:()=>i,toc:()=>u});var n=t(5893),c=t(1151);const d={title:"Code of Conduct"},s=void 0,i={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v0.5.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v0.5.x/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v0.5.x/contributing"}},r={},u=[];function a(e){const o={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["This project has adopted the ",(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"Resources:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:o}={...(0,c.a)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,o,t)=>{t.d(o,{Z:()=>i,a:()=>s});var n=t(7294);const c={},d=n.createContext(c);function s(e){const o=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(d.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/11d58a17.d706823d.js b/docs/assets/js/11d58a17.d706823d.js deleted file mode 100644 index 11bd1d816c..0000000000 --- a/docs/assets/js/11d58a17.d706823d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[154],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"version-v0.5.x/code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v0.5.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v0.5.x/code-of-conduct",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v0.5.x/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/12682444.4416d267.js b/docs/assets/js/12682444.4416d267.js deleted file mode 100644 index 95e52bba94..0000000000 --- a/docs/assets/js/12682444.4416d267.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3514],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=o,d=f["".concat(s,".").concat(m)]||f[m]||p[m]||a;return r?n.createElement(d,i(i({ref:t},u),{},{components:r})):n.createElement(d,i({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(7462),o=(r(7294),r(3905));const a={title:"Customization"},i=void 0,l={unversionedId:"customization",id:"version-v0.5.x/customization",title:"Customization",description:"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:",source:"@site/versioned_docs/version-v0.5.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v0.5.x/customization",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v0.5.x/exclusion"},next:{title:"Setup",permalink:"/eraser/docs/v0.5.x/setup"}},s={},c=[],u={toc:c};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"--job-cleanup-on-success-delay"),": Duration to delay job deletion after successful runs. 0 means no delay. Defaults to ",(0,o.kt)("inlineCode",{parentName:"li"},"0"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"--job-cleanup-on-error-delay"),": Duration to delay job deletion after errored runs. 0 means no delay. Defaults to ",(0,o.kt)("inlineCode",{parentName:"li"},"24h"),". "),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"--job-success-ratio"),": Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to ",(0,o.kt)("inlineCode",{parentName:"li"},"1.0"),". ")),(0,o.kt)("p",null,'For duration, valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/12682444.bf167c14.js b/docs/assets/js/12682444.bf167c14.js new file mode 100644 index 0000000000..7602043f2b --- /dev/null +++ b/docs/assets/js/12682444.bf167c14.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3514],{5230:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=s(5893),o=s(1151);const i={title:"Customization"},r=void 0,c={id:"customization",title:"Customization",description:"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:",source:"@site/versioned_docs/version-v0.5.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v0.5.x/customization",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v0.5.x/exclusion"},next:{title:"Setup",permalink:"/eraser/docs/v0.5.x/setup"}},a={},l=[];function u(e){const t={code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"--job-cleanup-on-success-delay"}),": Duration to delay job deletion after successful runs. 0 means no delay. Defaults to ",(0,n.jsx)(t.code,{children:"0"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"--job-cleanup-on-error-delay"}),": Duration to delay job deletion after errored runs. 0 means no delay. Defaults to ",(0,n.jsx)(t.code,{children:"24h"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"--job-success-ratio"}),": Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to ",(0,n.jsx)(t.code,{children:"1.0"}),"."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:'For duration, valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'})]})}function d(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},1151:(e,t,s)=>{s.d(t,{Z:()=>c,a:()=>r});var n=s(7294);const o={},i=n.createContext(o);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/1426.be67a35e.js b/docs/assets/js/1426.be67a35e.js new file mode 100644 index 0000000000..353f52faae --- /dev/null +++ b/docs/assets/js/1426.be67a35e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1426],{1426:(e,t,r)=>{function n(e,t){var r=void 0;return function(){for(var n=arguments.length,o=new Array(n),i=0;ipn});var a=function(){};function c(e){var t=e.item,r=e.items;return{index:t.__autocomplete_indexName,items:[t],positions:[1+r.findIndex((function(e){return e.objectID===t.objectID}))],queryID:t.__autocomplete_queryID,algoliaSource:["autocomplete"]}}function l(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,o,i,a,c=[],l=!0,u=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;l=!1}else for(;!(l=(n=i.call(r)).done)&&(c.push(n.value),c.length!==t);l=!0);}catch(s){u=!0,o=s}finally{try{if(!l&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(u)throw o}}return c}}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return u(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return u(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);re.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function y(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function h(e){for(var t=1;t=3||2===r&&n>=4||1===r&&n>=10);function i(t,r,n){if(o&&void 0!==n){var i=n[0].__autocomplete_algoliaCredentials,a={"X-Algolia-Application-Id":i.appId,"X-Algolia-API-Key":i.apiKey};e.apply(void 0,[t].concat(p(r),[{headers:a}]))}else e.apply(void 0,[t].concat(p(r)))}return{init:function(t,r){e("init",{appId:t,apiKey:r})},setUserToken:function(t){e("setUserToken",t)},clickedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),r=0;r0&&i("clickedObjectIDsAfterSearch",g(t),t[0].items)},clickedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),r=0;r0&&i("clickedObjectIDs",g(t),t[0].items)},clickedFilters:function(){for(var t=arguments.length,r=new Array(t),n=0;n0&&e.apply(void 0,["clickedFilters"].concat(r))},convertedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),r=0;r0&&i("convertedObjectIDsAfterSearch",g(t),t[0].items)},convertedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),r=0;r0&&i("convertedObjectIDs",g(t),t[0].items)},convertedFilters:function(){for(var t=arguments.length,r=new Array(t),n=0;n0&&e.apply(void 0,["convertedFilters"].concat(r))},viewedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),r=0;r0&&t.reduce((function(e,t){var r=t.items,n=d(t,f);return[].concat(p(e),p(function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:20,r=[],n=0;n0&&e.apply(void 0,["viewedFilters"].concat(r))}}}function S(e){var t=e.items.reduce((function(e,t){var r;return e[t.__autocomplete_indexName]=(null!==(r=e[t.__autocomplete_indexName])&&void 0!==r?r:[]).concat(t),e}),{});return Object.keys(t).map((function(e){return{index:e,items:t[e],algoliaSource:["autocomplete"]}}))}function j(e){return e.objectID&&e.__autocomplete_indexName&&e.__autocomplete_queryID}function w(e){return w="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},w(e)}function E(e){return function(e){if(Array.isArray(e))return P(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return P(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return P(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function P(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r0&&C({onItemsChange:o,items:r,insights:f,state:t}))}}),0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(e){var t=e.setContext,r=e.onSelect,n=e.onActive;s("addAlgoliaAgent","insights-plugin"),t({algoliaInsightsPlugin:{__algoliaSearchParameters:{clickAnalytics:!0},insights:f}}),r((function(e){var t=e.item,r=e.state,n=e.event;j(t)&&l({state:r,event:n,insights:f,item:t,insightsEvents:[D({eventName:"Item Selected"},c({item:t,items:m.current}))]})})),n((function(e){var t=e.item,r=e.state,n=e.event;j(t)&&u({state:r,event:n,insights:f,item:t,insightsEvents:[D({eventName:"Item Active"},c({item:t,items:m.current}))]})}))},onStateChange:function(e){var t=e.state;p({state:t})},__autocomplete_pluginOptions:e}}function _(e){return _="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_(e)}function T(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function q(e,t,r){return(t=function(e){var t=function(e,t){if("object"!==_(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!==_(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"===_(t)?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function R(e,t,r){var n,o=t.initialState;return{getState:function(){return o},dispatch:function(n,i){var a=function(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r0},reshape:function(e){return e.sources}},e),{},{id:null!==(r=e.id)&&void 0!==r?r:"autocomplete-".concat(V++),plugins:o,initialState:X({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},e.initialState),onStateChange:function(t){var r;null===(r=e.onStateChange)||void 0===r||r.call(e,t),o.forEach((function(e){var r;return null===(r=e.onStateChange)||void 0===r?void 0:r.call(e,t)}))},onSubmit:function(t){var r;null===(r=e.onSubmit)||void 0===r||r.call(e,t),o.forEach((function(e){var r;return null===(r=e.onSubmit)||void 0===r?void 0:r.call(e,t)}))},onReset:function(t){var r;null===(r=e.onReset)||void 0===r||r.call(e,t),o.forEach((function(e){var r;return null===(r=e.onReset)||void 0===r?void 0:r.call(e,t)}))},getSources:function(r){return Promise.all([].concat(Q(o.map((function(e){return e.getSources}))),[e.getSources]).filter(Boolean).map((function(e){return function(e,t){var r=[];return Promise.resolve(e(t)).then((function(e){return Array.isArray(e),Promise.all(e.filter((function(e){return Boolean(e)})).map((function(e){if(e.sourceId,r.includes(e.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(e.sourceId)," is not unique."));r.push(e.sourceId);var t={getItemInputValue:function(e){return e.state.query},getItemUrl:function(){},onSelect:function(e){(0,e.setIsOpen)(!1)},onActive:a,onResolve:a};Object.keys(t).forEach((function(e){t[e].__default=!0}));var n=$($({},t),e);return Promise.resolve(n)})))}))}(e,r)}))).then((function(e){return L(e)})).then((function(e){return e.map((function(e){return X(X({},e),{},{onSelect:function(r){e.onSelect(r),t.forEach((function(e){var t;return null===(t=e.onSelect)||void 0===t?void 0:t.call(e,r)}))},onActive:function(r){e.onActive(r),t.forEach((function(e){var t;return null===(t=e.onActive)||void 0===t?void 0:t.call(e,r)}))},onResolve:function(r){e.onResolve(r),t.forEach((function(e){var t;return null===(t=e.onResolve)||void 0===t?void 0:t.call(e,r)}))}})}))}))},navigator:X({navigate:function(e){var t=e.itemUrl;n.location.assign(t)},navigateNewTab:function(e){var t=e.itemUrl,r=n.open(t,"_blank","noopener");null==r||r.focus()},navigateNewWindow:function(e){var t=e.itemUrl;n.open(t,"_blank","noopener")}},e.navigator)})}function te(e){return te="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},te(e)}function re(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function ne(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var Ie,De,Ae,ke=null,xe=(Ie=-1,De=-1,Ae=void 0,function(e){var t=++Ie;return Promise.resolve(e).then((function(e){return Ae&&t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var Me=/((gt|sm)-|galaxy nexus)|samsung[- ]|samsungbrowser/i;function He(e){return He="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},He(e)}var Fe=["props","refresh","store"],Ue=["inputElement","formElement","panelElement"],Be=["inputElement"],Ve=["inputElement","maxLength"],Ke=["sourceIndex"],$e=["sourceIndex"],Je=["item","source","sourceIndex"];function ze(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function We(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Ge(e){var t=e.props,r=e.refresh,n=e.store,o=Ze(e,Fe),i=function(e,t){return void 0!==t?"".concat(e,"-").concat(t):e};return{getEnvironmentProps:function(e){var r=e.inputElement,o=e.formElement,i=e.panelElement;function a(e){!n.getState().isOpen&&n.pendingRequests.isEmpty()||e.target===r||!1===[o,i].some((function(t){return r=t,n=e.target,r===n||r.contains(n);var r,n}))&&(n.dispatch("blur",null),t.debug||n.pendingRequests.cancelAll())}return We({onTouchStart:a,onMouseDown:a,onTouchMove:function(e){!1!==n.getState().isOpen&&r===t.environment.document.activeElement&&e.target!==r&&r.blur()}},Ze(e,Ue))},getRootProps:function(e){return We({role:"combobox","aria-expanded":n.getState().isOpen,"aria-haspopup":"listbox","aria-owns":n.getState().isOpen?"".concat(t.id,"-list"):void 0,"aria-labelledby":"".concat(t.id,"-label")},e)},getFormProps:function(e){e.inputElement;return We({action:"",noValidate:!0,role:"search",onSubmit:function(i){var a;i.preventDefault(),t.onSubmit(We({event:i,refresh:r,state:n.getState()},o)),n.dispatch("submit",null),null===(a=e.inputElement)||void 0===a||a.blur()},onReset:function(i){var a;i.preventDefault(),t.onReset(We({event:i,refresh:r,state:n.getState()},o)),n.dispatch("reset",null),null===(a=e.inputElement)||void 0===a||a.focus()}},Ze(e,Be))},getLabelProps:function(e){var r=e||{},n=r.sourceIndex,o=Ze(r,Ke);return We({htmlFor:"".concat(i(t.id,n),"-input"),id:"".concat(i(t.id,n),"-label")},o)},getInputProps:function(e){var i;function c(e){(t.openOnFocus||Boolean(n.getState().query))&&Ce(We({event:e,props:t,query:n.getState().completion||n.getState().query,refresh:r,store:n},o)),n.dispatch("focus",null)}var l=e||{},u=(l.inputElement,l.maxLength),s=void 0===u?512:u,f=Ze(l,Ve),m=ge(n.getState()),p=function(e){return Boolean(e&&e.match(Me))}((null===(i=t.environment.navigator)||void 0===i?void 0:i.userAgent)||""),v=null!=m&&m.itemUrl&&!p?"go":"search";return We({"aria-autocomplete":"both","aria-activedescendant":n.getState().isOpen&&null!==n.getState().activeItemId?"".concat(t.id,"-item-").concat(n.getState().activeItemId):void 0,"aria-controls":n.getState().isOpen?"".concat(t.id,"-list"):void 0,"aria-labelledby":"".concat(t.id,"-label"),value:n.getState().completion||n.getState().query,id:"".concat(t.id,"-input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:v,spellCheck:"false",autoFocus:t.autoFocus,placeholder:t.placeholder,maxLength:s,type:"search",onChange:function(e){Ce(We({event:e,props:t,query:e.currentTarget.value.slice(0,s),refresh:r,store:n},o))},onKeyDown:function(e){!function(e){var t=e.event,r=e.props,n=e.refresh,o=e.store,i=Le(e,_e);if("ArrowUp"===t.key||"ArrowDown"===t.key){var a=function(){var e=r.environment.document.getElementById("".concat(r.id,"-item-").concat(o.getState().activeItemId));e&&(e.scrollIntoViewIfNeeded?e.scrollIntoViewIfNeeded(!1):e.scrollIntoView(!1))},c=function(){var e=ge(o.getState());if(null!==o.getState().activeItemId&&e){var r=e.item,a=e.itemInputValue,c=e.itemUrl,l=e.source;l.onActive(qe({event:t,item:r,itemInputValue:a,itemUrl:c,refresh:n,source:l,state:o.getState()},i))}};t.preventDefault(),!1===o.getState().isOpen&&(r.openOnFocus||Boolean(o.getState().query))?Ce(qe({event:t,props:r,query:o.getState().query,refresh:n,store:o},i)).then((function(){o.dispatch(t.key,{nextActiveItemId:r.defaultActiveItemId}),c(),setTimeout(a,0)})):(o.dispatch(t.key,{}),c(),a())}else if("Escape"===t.key)t.preventDefault(),o.dispatch(t.key,null),o.pendingRequests.cancelAll();else if("Tab"===t.key)o.dispatch("blur",null),o.pendingRequests.cancelAll();else if("Enter"===t.key){if(null===o.getState().activeItemId||o.getState().collections.every((function(e){return 0===e.items.length})))return void(r.debug||o.pendingRequests.cancelAll());t.preventDefault();var l=ge(o.getState()),u=l.item,s=l.itemInputValue,f=l.itemUrl,m=l.source;if(t.metaKey||t.ctrlKey)void 0!==f&&(m.onSelect(qe({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},i)),r.navigator.navigateNewTab({itemUrl:f,item:u,state:o.getState()}));else if(t.shiftKey)void 0!==f&&(m.onSelect(qe({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},i)),r.navigator.navigateNewWindow({itemUrl:f,item:u,state:o.getState()}));else if(t.altKey);else{if(void 0!==f)return m.onSelect(qe({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},i)),void r.navigator.navigate({itemUrl:f,item:u,state:o.getState()});Ce(qe({event:t,nextState:{isOpen:!1},props:r,query:s,refresh:n,store:o},i)).then((function(){m.onSelect(qe({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},i))}))}}}(We({event:e,props:t,refresh:r,store:n},o))},onFocus:c,onBlur:a,onClick:function(r){e.inputElement!==t.environment.document.activeElement||n.getState().isOpen||c(r)}},f)},getPanelProps:function(e){return We({onMouseDown:function(e){e.preventDefault()},onMouseLeave:function(){n.dispatch("mouseleave",null)}},e)},getListProps:function(e){var r=e||{},n=r.sourceIndex,o=Ze(r,$e);return We({role:"listbox","aria-labelledby":"".concat(i(t.id,n),"-label"),id:"".concat(i(t.id,n),"-list")},o)},getItemProps:function(e){var a=e.item,c=e.source,l=e.sourceIndex,u=Ze(e,Je);return We({id:"".concat(i(t.id,l),"-item-").concat(a.__autocomplete_id),role:"option","aria-selected":n.getState().activeItemId===a.__autocomplete_id,onMouseMove:function(e){if(a.__autocomplete_id!==n.getState().activeItemId){n.dispatch("mousemove",a.__autocomplete_id);var t=ge(n.getState());if(null!==n.getState().activeItemId&&t){var i=t.item,c=t.itemInputValue,l=t.itemUrl,u=t.source;u.onActive(We({event:e,item:i,itemInputValue:c,itemUrl:l,refresh:r,source:u,state:n.getState()},o))}}},onMouseDown:function(e){e.preventDefault()},onClick:function(e){var i=c.getItemInputValue({item:a,state:n.getState()}),l=c.getItemUrl({item:a,state:n.getState()});(l?Promise.resolve():Ce(We({event:e,nextState:{isOpen:!1},props:t,query:i,refresh:r,store:n},o))).then((function(){c.onSelect(We({event:e,item:a,itemInputValue:i,itemUrl:l,refresh:r,source:c,state:n.getState()},o))}))}},u)}}}var Xe=[{segment:"autocomplete-core",version:"1.9.3"}];function Ye(e){return Ye="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ye(e)}function et(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function tt(e){for(var t=1;t=r?null===n?null:0:o}function at(e){return at="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},at(e)}function ct(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function lt(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function kt(e){var t=e.translations,r=void 0===t?{}:t,n=At(e,Pt),o=r.noResultsText,i=void 0===o?"No results for":o,a=r.suggestedQueryText,c=void 0===a?"Try searching for":a,l=r.reportMissingResultsText,u=void 0===l?"Believe this query should return results?":l,s=r.reportMissingResultsLinkText,f=void 0===s?"Let us know.":s,m=n.state.context.searchSuggestions;return yt.createElement("div",{className:"DocSearch-NoResults"},yt.createElement("div",{className:"DocSearch-Screen-Icon"},yt.createElement(Et,null)),yt.createElement("p",{className:"DocSearch-Title"},i,' "',yt.createElement("strong",null,n.state.query),'"'),m&&m.length>0&&yt.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},yt.createElement("p",{className:"DocSearch-Help"},c,":"),yt.createElement("ul",null,m.slice(0,3).reduce((function(e,t){return[].concat(It(e),[yt.createElement("li",{key:t},yt.createElement("button",{className:"DocSearch-Prefill",key:t,type:"button",onClick:function(){n.setQuery(t.toLowerCase()+" "),n.refresh(),n.inputRef.current.focus()}},t))])}),[]))),n.getMissingResultsUrl&&yt.createElement("p",{className:"DocSearch-Help"},"".concat(u," "),yt.createElement("a",{href:n.getMissingResultsUrl({query:n.state.query}),target:"_blank",rel:"noopener noreferrer"},f)))}var xt=function(){return yt.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},yt.createElement("path",{d:"M17 6v12c0 .52-.2 1-1 1H4c-.7 0-1-.33-1-1V2c0-.55.42-1 1-1h8l5 5zM14 8h-3.13c-.51 0-.87-.34-.87-.87V4",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))};function Ct(e){switch(e.type){case"lvl1":return yt.createElement(xt,null);case"content":return yt.createElement(_t,null);default:return yt.createElement(Nt,null)}}function Nt(){return yt.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},yt.createElement("path",{d:"M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function _t(){return yt.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},yt.createElement("path",{d:"M17 5H3h14zm0 5H3h14zm0 5H3h14z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function Tt(){return yt.createElement("svg",{className:"DocSearch-Hit-Select-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},yt.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},yt.createElement("path",{d:"M18 3v4c0 2-2 4-4 4H2"}),yt.createElement("path",{d:"M8 17l-6-6 6-6"})))}var qt=["hit","attribute","tagName"];function Rt(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function Lt(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Ft(e,t){return t.split(".").reduce((function(e,t){return null!=e&&e[t]?e[t]:null}),e)}function Ut(e){var t=e.hit,r=e.attribute,n=e.tagName,o=void 0===n?"span":n,i=Ht(e,qt);return(0,yt.createElement)(o,Lt(Lt({},i),{},{dangerouslySetInnerHTML:{__html:Ft(t,"_snippetResult.".concat(r,".value"))||Ft(t,r)}}))}function Bt(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==r)return;var n,o,i=[],a=!0,c=!1;try{for(r=r.call(e);!(a=(n=r.next()).done)&&(i.push(n.value),!t||i.length!==t);a=!0);}catch(l){c=!0,o=l}finally{try{a||null==r.return||r.return()}finally{if(c)throw o}}return i}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return Vt(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return Vt(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Vt(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r|<\/mark>)/g,Wt=RegExp(zt.source);function Qt(e){var t,r,n=e;if(!n.__docsearch_parent&&!e._highlightResult)return e.hierarchy.lvl0;var o=((n.__docsearch_parent?null===(t=n.__docsearch_parent)||void 0===t||null===(t=t._highlightResult)||void 0===t||null===(t=t.hierarchy)||void 0===t?void 0:t.lvl0:null===(r=e._highlightResult)||void 0===r||null===(r=r.hierarchy)||void 0===r?void 0:r.lvl0)||{}).value;return o&&Wt.test(o)?o.replace(zt,""):o}function Zt(){return Zt=Object.assign||function(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function or(e){var t=e.translations,r=void 0===t?{}:t,n=nr(e,tr),o=r.recentSearchesTitle,i=void 0===o?"Recent":o,a=r.noRecentSearchesText,c=void 0===a?"No recent searches":a,l=r.saveRecentSearchButtonTitle,u=void 0===l?"Save this search":l,s=r.removeRecentSearchButtonTitle,f=void 0===s?"Remove this search from history":s,m=r.favoriteSearchesTitle,p=void 0===m?"Favorite":m,v=r.removeFavoriteSearchButtonTitle,d=void 0===v?"Remove this search from favorites":v;return"idle"===n.state.status&&!1===n.hasCollections?n.disableUserPersonalization?null:yt.createElement("div",{className:"DocSearch-StartScreen"},yt.createElement("p",{className:"DocSearch-Help"},c)):!1===n.hasCollections?null:yt.createElement("div",{className:"DocSearch-Dropdown-Container"},yt.createElement($t,rr({},n,{title:i,collection:n.state.collections[0],renderIcon:function(){return yt.createElement("div",{className:"DocSearch-Hit-icon"},yt.createElement(Xt,null))},renderAction:function(e){var t=e.item,r=e.runFavoriteTransition,o=e.runDeleteTransition;return yt.createElement(yt.Fragment,null,yt.createElement("div",{className:"DocSearch-Hit-action"},yt.createElement("button",{className:"DocSearch-Hit-action-button",title:u,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),r((function(){n.favoriteSearches.add(t),n.recentSearches.remove(t),n.refresh()}))}},yt.createElement(Yt,null))),yt.createElement("div",{className:"DocSearch-Hit-action"},yt.createElement("button",{className:"DocSearch-Hit-action-button",title:f,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),o((function(){n.recentSearches.remove(t),n.refresh()}))}},yt.createElement(er,null))))}})),yt.createElement($t,rr({},n,{title:p,collection:n.state.collections[1],renderIcon:function(){return yt.createElement("div",{className:"DocSearch-Hit-icon"},yt.createElement(Yt,null))},renderAction:function(e){var t=e.item,r=e.runDeleteTransition;return yt.createElement("div",{className:"DocSearch-Hit-action"},yt.createElement("button",{className:"DocSearch-Hit-action-button",title:d,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),r((function(){n.favoriteSearches.remove(t),n.refresh()}))}},yt.createElement(er,null)))}})))}var ir=["translations"];function ar(){return ar=Object.assign||function(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var lr=yt.memo((function(e){var t=e.translations,r=void 0===t?{}:t,n=cr(e,ir);if("error"===n.state.status)return yt.createElement(wt,{translations:null==r?void 0:r.errorScreen});var o=n.state.collections.some((function(e){return e.items.length>0}));return n.state.query?!1===o?yt.createElement(kt,ar({},n,{translations:null==r?void 0:r.noResultsScreen})):yt.createElement(Gt,n):yt.createElement(or,ar({},n,{hasCollections:o,translations:null==r?void 0:r.startScreen}))}),(function(e,t){return"loading"===t.state.status||"stalled"===t.state.status}));function ur(){return yt.createElement("svg",{viewBox:"0 0 38 38",stroke:"currentColor",strokeOpacity:".5"},yt.createElement("g",{fill:"none",fillRule:"evenodd"},yt.createElement("g",{transform:"translate(1 1)",strokeWidth:"2"},yt.createElement("circle",{strokeOpacity:".3",cx:"18",cy:"18",r:"18"}),yt.createElement("path",{d:"M36 18c0-9.94-8.06-18-18-18"},yt.createElement("animateTransform",{attributeName:"transform",type:"rotate",from:"0 18 18",to:"360 18 18",dur:"1s",repeatCount:"indefinite"})))))}var sr=r(830),fr=["translations"];function mr(){return mr=Object.assign||function(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function vr(e){var t=e.translations,r=void 0===t?{}:t,n=pr(e,fr),o=r.resetButtonTitle,i=void 0===o?"Clear the query":o,a=r.resetButtonAriaLabel,c=void 0===a?"Clear the query":a,l=r.cancelButtonText,u=void 0===l?"Cancel":l,s=r.cancelButtonAriaLabel,f=void 0===s?"Cancel":s,m=n.getFormProps({inputElement:n.inputRef.current}).onReset;return yt.useEffect((function(){n.autoFocus&&n.inputRef.current&&n.inputRef.current.focus()}),[n.autoFocus,n.inputRef]),yt.useEffect((function(){n.isFromSelection&&n.inputRef.current&&n.inputRef.current.select()}),[n.isFromSelection,n.inputRef]),yt.createElement(yt.Fragment,null,yt.createElement("form",{className:"DocSearch-Form",onSubmit:function(e){e.preventDefault()},onReset:m},yt.createElement("label",mr({className:"DocSearch-MagnifierLabel"},n.getLabelProps()),yt.createElement(sr.W,null)),yt.createElement("div",{className:"DocSearch-LoadingIndicator"},yt.createElement(ur,null)),yt.createElement("input",mr({className:"DocSearch-Input",ref:n.inputRef},n.getInputProps({inputElement:n.inputRef.current,autoFocus:n.autoFocus,maxLength:ht}))),yt.createElement("button",{type:"reset",title:i,className:"DocSearch-Reset","aria-label":c,hidden:!n.state.query},yt.createElement(er,null))),yt.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":f,onClick:n.onClose},u))}var dr=["_highlightResult","_snippetResult"];function yr(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function hr(e){return!1===function(){var e="__TEST_KEY__";try{return localStorage.setItem(e,""),localStorage.removeItem(e),!0}catch(t){return!1}}()?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(t){return window.localStorage.setItem(e,JSON.stringify(t))},getItem:function(){var t=window.localStorage.getItem(e);return t?JSON.parse(t):[]}}}function br(e){var t=e.key,r=e.limit,n=void 0===r?5:r,o=hr(t),i=o.getItem().slice(0,n);return{add:function(e){var t=e,r=(t._highlightResult,t._snippetResult,yr(t,dr)),a=i.findIndex((function(e){return e.objectID===r.objectID}));a>-1&&i.splice(a,1),i.unshift(r),i=i.slice(0,n),o.setItem(i)},remove:function(e){i=i.filter((function(t){return t.objectID!==e.objectID})),o.setItem(i)},getAll:function(){return i}}}function gr(e){const t=`algoliasearch-client-js-${e.key}`;let r;const n=()=>(void 0===r&&(r=e.localStorage||window.localStorage),r),o=()=>JSON.parse(n().getItem(t)||"{}"),i=e=>{n().setItem(t,JSON.stringify(e))};return{get:(t,r,n={miss:()=>Promise.resolve()})=>Promise.resolve().then((()=>{(()=>{const t=e.timeToLive?1e3*e.timeToLive:null,r=o(),n=Object.fromEntries(Object.entries(r).filter((([,e])=>void 0!==e.timestamp)));if(i(n),!t)return;const a=Object.fromEntries(Object.entries(n).filter((([,e])=>{const r=(new Date).getTime();return!(e.timestamp+tPromise.all([e?e.value:r(),void 0!==e]))).then((([e,t])=>Promise.all([e,t||n.miss(e)]))).then((([e])=>e)),set:(e,r)=>Promise.resolve().then((()=>{const i=o();return i[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:r},n().setItem(t,JSON.stringify(i)),r})),delete:e=>Promise.resolve().then((()=>{const r=o();delete r[JSON.stringify(e)],n().setItem(t,JSON.stringify(r))})),clear:()=>Promise.resolve().then((()=>{n().removeItem(t)}))}}function Or(e){const t=[...e.caches],r=t.shift();return void 0===r?{get:(e,t,r={miss:()=>Promise.resolve()})=>t().then((e=>Promise.all([e,r.miss(e)]))).then((([e])=>e)),set:(e,t)=>Promise.resolve(t),delete:e=>Promise.resolve(),clear:()=>Promise.resolve()}:{get:(e,n,o={miss:()=>Promise.resolve()})=>r.get(e,n,o).catch((()=>Or({caches:t}).get(e,n,o))),set:(e,n)=>r.set(e,n).catch((()=>Or({caches:t}).set(e,n))),delete:e=>r.delete(e).catch((()=>Or({caches:t}).delete(e))),clear:()=>r.clear().catch((()=>Or({caches:t}).clear()))}}function Sr(e={serializable:!0}){let t={};return{get(r,n,o={miss:()=>Promise.resolve()}){const i=JSON.stringify(r);if(i in t)return Promise.resolve(e.serializable?JSON.parse(t[i]):t[i]);const a=n(),c=o&&o.miss||(()=>Promise.resolve());return a.then((e=>c(e))).then((()=>a))},set:(r,n)=>(t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)),delete:e=>(delete t[JSON.stringify(e)],Promise.resolve()),clear:()=>(t={},Promise.resolve())}}function jr(e){let t=e.length-1;for(;t>0;t--){const r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function wr(e,t){return t?(Object.keys(t).forEach((r=>{e[r]=t[r](e)})),e):e}function Er(e,...t){let r=0;return e.replace(/%s/g,(()=>encodeURIComponent(t[r++])))}const Pr="4.22.1",Ir={WithinQueryParameters:0,WithinHeaders:1};function Dr(e,t){const r=e||{},n=r.data||{};return Object.keys(r).forEach((e=>{-1===["timeout","headers","queryParameters","data","cacheable"].indexOf(e)&&(n[e]=r[e])})),{data:Object.entries(n).length>0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}const Ar={Read:1,Write:2,Any:3},kr={Up:1,Down:2,Timeouted:3},xr=12e4;function Cr(e,t=kr.Up){return{...e,status:t,lastUpdate:Date.now()}}function Nr(e){return"string"==typeof e?{protocol:"https",url:e,accept:Ar.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||Ar.Any}}const _r={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};function Tr(e,t){return Promise.all(t.map((t=>e.get(t,(()=>Promise.resolve(Cr(t))))))).then((e=>{const r=e.filter((e=>function(e){return e.status===kr.Up||Date.now()-e.lastUpdate>xr}(e))),n=e.filter((e=>function(e){return e.status===kr.Timeouted&&Date.now()-e.lastUpdate<=xr}(e))),o=[...r,...n];return{getTimeout:(e,t)=>(0===n.length&&0===e?1:n.length+3+e)*t,statelessHosts:o.length>0?o.map((e=>Nr(e))):t}}))}const qr=(e,t)=>(e=>{const t=e.status;return e.isTimedOut||(({isTimedOut:e,status:t})=>!e&&0==~~t)(e)||2!=~~(t/100)&&4!=~~(t/100)})(e)?t.onRetry(e):(({status:e})=>2==~~(e/100))(e)?t.onSuccess(e):t.onFail(e);function Rr(e,t,r,n){const o=[],i=function(e,t){if(e.method===_r.Get||void 0===e.data&&void 0===t.data)return;const r=Array.isArray(e.data)?e.data:{...e.data,...t.data};return JSON.stringify(r)}(r,n),a=function(e,t){const r={...e.headers,...t.headers},n={};return Object.keys(r).forEach((e=>{const t=r[e];n[e.toLowerCase()]=t})),n}(e,n),c=r.method,l=r.method!==_r.Get?{}:{...r.data,...n.data},u={"x-algolia-agent":e.userAgent.value,...e.queryParameters,...l,...n.queryParameters};let s=0;const f=(t,l)=>{const m=t.pop();if(void 0===m)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:Fr(o)};const p={data:i,headers:a,method:c,url:Mr(m,r.path,u),connectTimeout:l(s,e.timeouts.connect),responseTimeout:l(s,n.timeout)},v=e=>{const r={request:p,response:e,host:m,triesLeft:t.length};return o.push(r),r},d={onSuccess:e=>function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e),onRetry(r){const n=v(r);return r.isTimedOut&&s++,Promise.all([e.logger.info("Retryable failure",Ur(n)),e.hostsCache.set(m,Cr(m,r.isTimedOut?kr.Timeouted:kr.Down))]).then((()=>f(t,l)))},onFail(e){throw v(e),function({content:e,status:t},r){let n=e;try{n=JSON.parse(e).message}catch(o){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(n,t,r)}(e,Fr(o))}};return e.requester.send(p).then((e=>qr(e,d)))};return Tr(e.hostsCache,t).then((e=>f([...e.statelessHosts].reverse(),e.getTimeout)))}function Lr(e){const t={value:`Algolia for JavaScript (${e})`,add(e){const r=`; ${e.segment}${void 0!==e.version?` (${e.version})`:""}`;return-1===t.value.indexOf(r)&&(t.value=`${t.value}${r}`),t}};return t}function Mr(e,t,r){const n=Hr(r);let o=`${e.protocol}://${e.url}/${"/"===t.charAt(0)?t.substr(1):t}`;return n.length&&(o+=`?${n}`),o}function Hr(e){return Object.keys(e).map((t=>{return Er("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function Fr(e){return e.map((e=>Ur(e)))}function Ur(e){const t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...e,request:{...e.request,headers:{...e.request.headers,...t}}}}const Br=e=>{const t=e.appId,r=function(e,t,r){const n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:()=>e===Ir.WithinHeaders?n:{},queryParameters:()=>e===Ir.WithinQueryParameters?n:{}}}(void 0!==e.authMode?e.authMode:Ir.WithinHeaders,t,e.apiKey),n=function(e){const{hostsCache:t,logger:r,requester:n,requestsCache:o,responsesCache:i,timeouts:a,userAgent:c,hosts:l,queryParameters:u,headers:s}=e,f={hostsCache:t,logger:r,requester:n,requestsCache:o,responsesCache:i,timeouts:a,userAgent:c,headers:s,queryParameters:u,hosts:l.map((e=>Nr(e))),read(e,t){const r=Dr(t,f.timeouts.read),n=()=>Rr(f,f.hosts.filter((e=>0!=(e.accept&Ar.Read))),e,r);if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();const o={request:e,mappedRequestOptions:r,transporter:{queryParameters:f.queryParameters,headers:f.headers}};return f.responsesCache.get(o,(()=>f.requestsCache.get(o,(()=>f.requestsCache.set(o,n()).then((e=>Promise.all([f.requestsCache.delete(o),e])),(e=>Promise.all([f.requestsCache.delete(o),Promise.reject(e)]))).then((([e,t])=>t))))),{miss:e=>f.responsesCache.set(o,e)})},write:(e,t)=>Rr(f,f.hosts.filter((e=>0!=(e.accept&Ar.Write))),e,Dr(t,f.timeouts.write))};return f}({hosts:[{url:`${t}-dsn.algolia.net`,accept:Ar.Read},{url:`${t}.algolia.net`,accept:Ar.Write}].concat(jr([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}])),...e,headers:{...r.headers(),"content-type":"application/x-www-form-urlencoded",...e.headers},queryParameters:{...r.queryParameters(),...e.queryParameters}}),o={transporter:n,appId:t,addAlgoliaAgent(e,t){n.userAgent.add({segment:e,version:t})},clearCache:()=>Promise.all([n.requestsCache.clear(),n.responsesCache.clear()]).then((()=>{}))};return wr(o,e.methods)},Vr=e=>(t,r)=>t.method===_r.Get?e.transporter.read(t,r):e.transporter.write(t,r),Kr=e=>(t,r={})=>wr({transporter:e.transporter,appId:e.appId,indexName:t},r.methods),$r=e=>(t,r)=>{const n=t.map((e=>({...e,params:Hr(e.params||{})})));return e.transporter.read({method:_r.Post,path:"1/indexes/*/queries",data:{requests:n},cacheable:!0},r)},Jr=e=>(t,r)=>Promise.all(t.map((t=>{const{facetName:n,facetQuery:o,...i}=t.params;return Kr(e)(t.indexName,{methods:{searchForFacetValues:Qr}}).searchForFacetValues(n,o,{...r,...i})}))),zr=e=>(t,r,n)=>e.transporter.read({method:_r.Post,path:Er("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},n),Wr=e=>(t,r)=>e.transporter.read({method:_r.Post,path:Er("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r),Qr=e=>(t,r,n)=>e.transporter.read({method:_r.Post,path:Er("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n),Zr={Debug:1,Info:2,Error:3};function Gr(e,t,r){const n={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:e=>new Promise((t=>{const r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((t=>r.setRequestHeader(t,e.headers[t])));const n=(e,n)=>setTimeout((()=>{r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e),o=n(e.connectTimeout,"Connection timeout");let i;r.onreadystatechange=()=>{r.readyState>r.OPENED&&void 0===i&&(clearTimeout(o),i=n(e.responseTimeout,"Socket timeout"))},r.onerror=()=>{0===r.status&&(clearTimeout(o),clearTimeout(i),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=()=>{clearTimeout(o),clearTimeout(i),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))},logger:(o=Zr.Error,{debug:(e,t)=>(Zr.Debug>=o&&console.debug(e,t),Promise.resolve()),info:(e,t)=>(Zr.Info>=o&&console.info(e,t),Promise.resolve()),error:(e,t)=>(console.error(e,t),Promise.resolve())}),responsesCache:Sr(),requestsCache:Sr({serializable:!1}),hostsCache:Or({caches:[gr({key:`${Pr}-${e}`}),Sr()]}),userAgent:Lr(Pr).add({segment:"Browser",version:"lite"}),authMode:Ir.WithinQueryParameters};var o;return Br({...n,...r,methods:{search:$r,searchForFacetValues:Jr,multipleQueries:$r,multipleSearchForFacetValues:Jr,customRequest:Vr,initIndex:e=>t=>Kr(e)(t,{methods:{search:Wr,searchForFacetValues:Qr,findAnswers:zr}})}})}Gr.version=Pr;const Xr=Gr;var Yr="3.5.2";function en(){}function tn(e){return e}function rn(e){return 1===e.button||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey}function nn(e,t,r){return e.reduce((function(e,n){var o=t(n);return e.hasOwnProperty(o)||(e[o]=[]),e[o].length<(r||5)&&e[o].push(n),e}),{})}var on=["footer","searchBox"];function an(){return an=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function pn(e){var t=e.appId,r=e.apiKey,n=e.indexName,o=e.placeholder,i=void 0===o?"Search docs":o,a=e.searchParameters,c=e.maxResultsPerGroup,l=e.onClose,u=void 0===l?en:l,s=e.transformItems,f=void 0===s?tn:s,m=e.hitComponent,p=void 0===m?St:m,v=e.resultsFooterComponent,d=void 0===v?function(){return null}:v,y=e.navigator,h=e.initialScrollY,b=void 0===h?0:h,g=e.transformSearchClient,O=void 0===g?tn:g,S=e.disableUserPersonalization,j=void 0!==S&&S,w=e.initialQuery,E=void 0===w?"":w,P=e.translations,I=void 0===P?{}:P,D=e.getMissingResultsUrl,A=e.insights,k=void 0!==A&&A,x=I.footer,C=I.searchBox,N=mn(I,on),_=sn(yt.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),T=_[0],q=_[1],R=yt.useRef(null),L=yt.useRef(null),M=yt.useRef(null),H=yt.useRef(null),F=yt.useRef(null),U=yt.useRef(10),B=yt.useRef("undefined"!=typeof window?window.getSelection().toString().slice(0,ht):"").current,V=yt.useRef(E||B).current,K=function(e,t,r){return yt.useMemo((function(){var n=Xr(e,t);return n.addAlgoliaAgent("docsearch",Yr),!1===/docsearch.js \(.*\)/.test(n.transporter.userAgent.value)&&n.addAlgoliaAgent("docsearch-react",Yr),r(n)}),[e,t,r])}(t,r,O),$=yt.useRef(br({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(n),limit:10})).current,J=yt.useRef(br({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(n),limit:0===$.getAll().length?7:4})).current,z=yt.useCallback((function(e){if(!j){var t="content"===e.type?e.__docsearch_parent:e;t&&-1===$.getAll().findIndex((function(e){return e.objectID===t.objectID}))&&J.add(t)}}),[$,J,j]),W=yt.useCallback((function(e){if(T.context.algoliaInsightsPlugin&&e.__autocomplete_id){var t=e,r={eventName:"Item Selected",index:t.__autocomplete_indexName,items:[t],positions:[e.__autocomplete_id],queryID:t.__autocomplete_queryID};T.context.algoliaInsightsPlugin.insights.clickedObjectIDsAfterSearch(r)}}),[T.context.algoliaInsightsPlugin]),Q=yt.useMemo((function(){return dt({id:"docsearch",defaultActiveItemId:0,placeholder:i,openOnFocus:!0,initialState:{query:V,context:{searchSuggestions:[]}},insights:k,navigator:y,onStateChange:function(e){q(e.state)},getSources:function(e){var o=e.query,i=e.state,l=e.setContext,s=e.setStatus;if(!o)return j?[]:[{sourceId:"recentSearches",onSelect:function(e){var t=e.item,r=e.event;z(t),rn(r)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return J.getAll()}},{sourceId:"favoriteSearches",onSelect:function(e){var t=e.item,r=e.event;z(t),rn(r)||u()},getItemUrl:function(e){return e.item.url},getItems:function(){return $.getAll()}}];var m=Boolean(k);return K.search([{query:o,indexName:n,params:ln({attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(U.current),"hierarchy.lvl2:".concat(U.current),"hierarchy.lvl3:".concat(U.current),"hierarchy.lvl4:".concat(U.current),"hierarchy.lvl5:".concat(U.current),"hierarchy.lvl6:".concat(U.current),"content:".concat(U.current)],snippetEllipsisText:"\u2026",highlightPreTag:"",highlightPostTag:"",hitsPerPage:20,clickAnalytics:m},a)}]).catch((function(e){throw"RetryError"===e.name&&s("error"),e})).then((function(e){var o=e.results[0],a=o.hits,s=o.nbHits,p=nn(a,(function(e){return Qt(e)}),c);i.context.searchSuggestions.length0&&(X(),F.current&&F.current.focus())}),[V,X]),yt.useEffect((function(){function e(){if(L.current){var e=.01*window.innerHeight;L.current.style.setProperty("--docsearch-vh","".concat(e,"px"))}}return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[]),yt.createElement("div",an({ref:R},G({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container","stalled"===T.status&&"DocSearch-Container--Stalled","error"===T.status&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(e){e.target===e.currentTarget&&u()}}),yt.createElement("div",{className:"DocSearch-Modal",ref:L},yt.createElement("header",{className:"DocSearch-SearchBar",ref:M},yt.createElement(vr,an({},Q,{state:T,autoFocus:0===V.length,inputRef:F,isFromSelection:Boolean(V)&&V===B,translations:C,onClose:u}))),yt.createElement("div",{className:"DocSearch-Dropdown",ref:H},yt.createElement(lr,an({},Q,{indexName:n,state:T,hitComponent:p,resultsFooterComponent:d,disableUserPersonalization:j,recentSearches:J,favoriteSearches:$,inputRef:F,translations:N,getMissingResultsUrl:D,onItemClick:function(e,t){W(e),z(e),rn(t)||u()}}))),yt.createElement("footer",{className:"DocSearch-Footer"},yt.createElement(Ot,{translations:x}))))}}}]); \ No newline at end of file diff --git a/docs/assets/js/1772.61f6592f.js b/docs/assets/js/1772.61f6592f.js new file mode 100644 index 0000000000..5a728994c3 --- /dev/null +++ b/docs/assets/js/1772.61f6592f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1772],{5658:(e,t,i)=>{i.d(t,{Z:()=>a});i(7294);var n=i(512),s=i(5999),o=i(2503),r=i(5893);function a(e){let{className:t}=e;return(0,r.jsx)("main",{className:(0,n.Z)("container margin-vert--xl",t),children:(0,r.jsx)("div",{className:"row",children:(0,r.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,r.jsx)(o.Z,{as:"h1",className:"hero__title",children:(0,r.jsx)(s.Z,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,r.jsx)("p",{children:(0,r.jsx)(s.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,r.jsx)("p",{children:(0,r.jsx)(s.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}},1772:(e,t,i)=>{i.r(t),i.d(t,{default:()=>l});i(7294);var n=i(5999),s=i(833),o=i(7372),r=i(5658),a=i(5893);function l(){const e=(0,n.I)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(s.d,{title:e}),(0,a.jsx)(o.Z,{children:(0,a.jsx)(r.Z,{})})]})}}}]); \ No newline at end of file diff --git a/docs/assets/js/17896441.5c745bdc.js b/docs/assets/js/17896441.5c745bdc.js deleted file mode 100644 index 84417a2f70..0000000000 --- a/docs/assets/js/17896441.5c745bdc.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7918],{3905:(e,t,n)=>{"use strict";n.d(t,{Zo:()=>m,kt:()=>p});var a=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=a.createContext({}),i=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},m=function(e){var t=i(e.components);return a.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,l=e.mdxType,r=e.originalType,s=e.parentName,m=c(e,["components","mdxType","originalType","parentName"]),u=i(n),p=l,f=u["".concat(s,".").concat(p)]||u[p]||d[p]||r;return n?a.createElement(f,o(o({ref:t},m),{},{components:n})):a.createElement(f,o({ref:t},m))}));function p(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var r=n.length,o=new Array(r);o[0]=u;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:l,o[1]=c;for(var i=2;i{"use strict";n.r(t),n.d(t,{default:()=>Dt});var a=n(7294),l=n(833),r=n(902);const o=a.createContext(null);function c(e){let{children:t,content:n}=e;const l=function(e){return(0,a.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return a.createElement(o.Provider,{value:l},t)}function s(){const e=(0,a.useContext)(o);if(null===e)throw new r.i6("DocProvider");return e}function i(){var e;const{metadata:t,frontMatter:n,assets:r}=s();return a.createElement(l.d,{title:t.title,description:t.description,keywords:n.keywords,image:null!=(e=r.image)?e:n.image})}var m=n(4334),d=n(7524),u=n(7462),p=n(5999),f=n(9960);function h(e){const{permalink:t,title:n,subLabel:l,isNext:r}=e;return a.createElement(f.Z,{className:(0,m.Z)("pagination-nav__link",r?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t},l&&a.createElement("div",{className:"pagination-nav__sublabel"},l),a.createElement("div",{className:"pagination-nav__label"},n))}function v(e){const{previous:t,next:n}=e;return a.createElement("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,p.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"})},t&&a.createElement(h,(0,u.Z)({},t,{subLabel:a.createElement(p.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc"},"Previous")})),n&&a.createElement(h,(0,u.Z)({},n,{subLabel:a.createElement(p.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc"},"Next"),isNext:!0})))}function g(){const{metadata:e}=s();return a.createElement(v,{previous:e.previous,next:e.next})}var b=n(2263),E=n(143),y=n(5281),k=n(373),N=n(4477);const L={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(p.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is unreleased documentation for {siteTitle} {versionLabel} version.")},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return a.createElement(p.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:a.createElement("b",null,n.label)}},"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.")}};function C(e){const t=L[e.versionMetadata.banner];return a.createElement(t,e)}function T(e){let{versionLabel:t,to:n,onClick:l}=e;return a.createElement(p.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:a.createElement("b",null,a.createElement(f.Z,{to:n,onClick:l},a.createElement(p.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label"},"latest version")))}},"For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).")}function _(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:l}}=(0,b.Z)(),{pluginId:r}=(0,E.gA)({failfast:!0}),{savePreferredVersionName:o}=(0,k.J)(r),{latestDocSuggestion:c,latestVersionSuggestion:s}=(0,E.Jo)(r),i=null!=c?c:(d=s).docs.find((e=>e.id===d.mainDocId));var d;return a.createElement("div",{className:(0,m.Z)(t,y.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert"},a.createElement("div",null,a.createElement(C,{siteTitle:l,versionMetadata:n})),a.createElement("div",{className:"margin-top--md"},a.createElement(T,{versionLabel:s.label,to:i.path,onClick:()=>o(s.name)})))}function w(e){let{className:t}=e;const n=(0,N.E)();return n.banner?a.createElement(_,{className:t,versionMetadata:n}):null}function Z(e){let{className:t}=e;const n=(0,N.E)();return n.badge?a.createElement("span",{className:(0,m.Z)(t,y.k.docs.docVersionBadge,"badge badge--secondary")},a.createElement(p.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label}},"Version: {versionLabel}")):null}function x(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n}=e;return a.createElement(p.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:a.createElement("b",null,a.createElement("time",{dateTime:new Date(1e3*t).toISOString()},n))}}," on {date}")}function B(e){let{lastUpdatedBy:t}=e;return a.createElement(p.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:a.createElement("b",null,t)}}," by {user}")}function O(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n,lastUpdatedBy:l}=e;return a.createElement("span",{className:y.k.common.lastUpdated},a.createElement(p.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t&&n?a.createElement(x,{lastUpdatedAt:t,formattedLastUpdatedAt:n}):"",byUser:l?a.createElement(B,{lastUpdatedBy:l}):""}},"Last updated{atDate}{byUser}"),!1)}const A="iconEdit_Z9Sw";function j(e){let{className:t,...n}=e;return a.createElement("svg",(0,u.Z)({fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,m.Z)(A,t),"aria-hidden":"true"},n),a.createElement("g",null,a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}function H(e){let{editUrl:t}=e;return a.createElement("a",{href:t,target:"_blank",rel:"noreferrer noopener",className:y.k.common.editThisPage},a.createElement(j,null),a.createElement(p.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page"},"Edit this page"))}const S="tag_zVej",M="tagRegular_sFm0",P="tagWithCount_h2kH";function I(e){let{permalink:t,label:n,count:l}=e;return a.createElement(f.Z,{href:t,className:(0,m.Z)(S,l?P:M)},n,l&&a.createElement("span",null,l))}const U="tags_jXut",z="tag_QGVx";function V(e){let{tags:t}=e;return a.createElement(a.Fragment,null,a.createElement("b",null,a.createElement(p.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list"},"Tags:")),a.createElement("ul",{className:(0,m.Z)(U,"padding--none","margin-left--sm")},t.map((e=>{let{label:t,permalink:n}=e;return a.createElement("li",{key:n,className:z},a.createElement(I,{label:t,permalink:n}))}))))}const D="lastUpdated_vwxv";function R(e){return a.createElement("div",{className:(0,m.Z)(y.k.docs.docFooterTagsRow,"row margin-bottom--sm")},a.createElement("div",{className:"col"},a.createElement(V,e)))}function W(e){let{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:l,formattedLastUpdatedAt:r}=e;return a.createElement("div",{className:(0,m.Z)(y.k.docs.docFooterEditMetaRow,"row")},a.createElement("div",{className:"col"},t&&a.createElement(H,{editUrl:t})),a.createElement("div",{className:(0,m.Z)("col",D)},(n||l)&&a.createElement(O,{lastUpdatedAt:n,formattedLastUpdatedAt:r,lastUpdatedBy:l})))}function F(){const{metadata:e}=s(),{editUrl:t,lastUpdatedAt:n,formattedLastUpdatedAt:l,lastUpdatedBy:r,tags:o}=e,c=o.length>0,i=!!(t||n||r);return c||i?a.createElement("footer",{className:(0,m.Z)(y.k.docs.docFooter,"docusaurus-mt-lg")},c&&a.createElement(R,{tags:o}),i&&a.createElement(W,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:r,formattedLastUpdatedAt:l})):null}var q=n(6043),G=n(6668);function Y(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const a=n.slice(2,e.level);e.parentIndex=Math.max(...a),n[e.level]=t}));const a=[];return t.forEach((e=>{const{parentIndex:n,...l}=e;n>=0?t[n].children.push(l):a.push(l)})),a}function $(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return t.flatMap((e=>{const t=$({toc:e.children,minHeadingLevel:n,maxHeadingLevel:a});return function(e){return e.level>=n&&e.level<=a}(e)?[{...e,children:t}]:t}))}function J(e){const t=e.getBoundingClientRect();return t.top===t.bottom?J(e.parentNode):t}function Q(e,t){var n;let{anchorTopOffset:a}=t;const l=e.find((e=>J(e).top>=a));if(l){var r;return function(e){return e.top>0&&e.bottom{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function K(e){const t=(0,a.useRef)(void 0),n=X();(0,a.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:a,linkActiveClassName:l,minHeadingLevel:r,maxHeadingLevel:o}=e;function c(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(a),c=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const a=[];for(let l=t;l<=n;l+=1)a.push("h"+l+".anchor");return Array.from(document.querySelectorAll(a.join()))}({minHeadingLevel:r,maxHeadingLevel:o}),s=Q(c,{anchorTopOffset:n.current}),i=e.find((e=>s&&s.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(l),e.classList.add(l),t.current=e):e.classList.remove(l)}(e,e===i)}))}return document.addEventListener("scroll",c),document.addEventListener("resize",c),c(),()=>{document.removeEventListener("scroll",c),document.removeEventListener("resize",c)}}),[e,n])}function ee(e){let{toc:t,className:n,linkClassName:l,isChild:r}=e;return t.length?a.createElement("ul",{className:r?void 0:n},t.map((e=>a.createElement("li",{key:e.id},a.createElement("a",{href:"#"+e.id,className:null!=l?l:void 0,dangerouslySetInnerHTML:{__html:e.value}}),a.createElement(ee,{isChild:!0,toc:e.children,className:n,linkClassName:l}))))):null}const te=a.memo(ee);function ne(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:l="table-of-contents__link",linkActiveClassName:r,minHeadingLevel:o,maxHeadingLevel:c,...s}=e;const i=(0,G.L)(),m=null!=o?o:i.tableOfContents.minHeadingLevel,d=null!=c?c:i.tableOfContents.maxHeadingLevel,p=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:l}=e;return(0,a.useMemo)((()=>$({toc:Y(t),minHeadingLevel:n,maxHeadingLevel:l})),[t,n,l])}({toc:t,minHeadingLevel:m,maxHeadingLevel:d});return K((0,a.useMemo)((()=>{if(l&&r)return{linkClassName:l,linkActiveClassName:r,minHeadingLevel:m,maxHeadingLevel:d}}),[l,r,m,d])),a.createElement(te,(0,u.Z)({toc:p,className:n,linkClassName:l},s))}const ae="tocCollapsibleButton_TO0P",le="tocCollapsibleButtonExpanded_MG3E";function re(e){let{collapsed:t,...n}=e;return a.createElement("button",(0,u.Z)({type:"button"},n,{className:(0,m.Z)("clean-btn",ae,!t&&le,n.className)}),a.createElement(p.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component"},"On this page"))}const oe="tocCollapsible_ETCw",ce="tocCollapsibleContent_vkbj",se="tocCollapsibleExpanded_sAul";function ie(e){let{toc:t,className:n,minHeadingLevel:l,maxHeadingLevel:r}=e;const{collapsed:o,toggleCollapsed:c}=(0,q.u)({initialState:!0});return a.createElement("div",{className:(0,m.Z)(oe,!o&&se,n)},a.createElement(re,{collapsed:o,onClick:c}),a.createElement(q.z,{lazy:!0,className:ce,collapsed:o},a.createElement(ne,{toc:t,minHeadingLevel:l,maxHeadingLevel:r})))}const me="tocMobile_ITEo";function de(){const{toc:e,frontMatter:t}=s();return a.createElement(ie,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,m.Z)(y.k.docs.docTocMobile,me)})}const ue="tableOfContents_bqdL";function pe(e){let{className:t,...n}=e;return a.createElement("div",{className:(0,m.Z)(ue,"thin-scrollbar",t)},a.createElement(ne,(0,u.Z)({},n,{linkClassName:"table-of-contents__link toc-highlight",linkActiveClassName:"table-of-contents__link--active"})))}function fe(){const{toc:e,frontMatter:t}=s();return a.createElement(pe,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:y.k.docs.docTocDesktop})}const he="anchorWithStickyNavbar_LWe7",ve="anchorWithHideOnScrollNavbar_WYt5";function ge(e){let{as:t,id:n,...l}=e;const{navbar:{hideOnScroll:r}}=(0,G.L)();if("h1"===t||!n)return a.createElement(t,(0,u.Z)({},l,{id:void 0}));const o=(0,p.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof l.children?l.children:n});return a.createElement(t,(0,u.Z)({},l,{className:(0,m.Z)("anchor",r?ve:he,l.className),id:n}),l.children,a.createElement(f.Z,{className:"hash-link",to:"#"+n,"aria-label":o,title:o},"\u200b"))}var be=n(3905),Ee=n(5742);var ye=n(2389),ke=n(2949);function Ne(){const{prism:e}=(0,G.L)(),{colorMode:t}=(0,ke.I)(),n=e.theme,a=e.darkTheme||n;return"dark"===t?a:n}var Le=n(7594),Ce=n.n(Le);const Te=/title=(?["'])(?.*?)\1/,_e=/\{(?<range>[\d,-]+)\}/,we={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}};function Ze(e,t){const n=e.map((e=>{const{start:n,end:a}=we[e];return"(?:"+n+"\\s*("+t.flatMap((e=>{var t,n;return[e.line,null==(t=e.block)?void 0:t.start,null==(n=e.block)?void 0:n.end].filter(Boolean)})).join("|")+")\\s*"+a+")"})).join("|");return new RegExp("^\\s*(?:"+n+")\\s*$")}function xe(e,t){let n=e.replace(/\n$/,"");const{language:a,magicComments:l,metastring:r}=t;if(r&&_e.test(r)){const e=r.match(_e).groups.range;if(0===l.length)throw new Error("A highlight range has been given in code block's metastring (``` "+r+"), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.");const t=l[0].className,a=Ce()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(a),code:n}}if(void 0===a)return{lineClassNames:{},code:n};const o=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return Ze(["js","jsBlock"],t);case"jsx":case"tsx":return Ze(["js","jsBlock","jsx"],t);case"html":return Ze(["js","jsBlock","html"],t);case"python":case"py":case"bash":return Ze(["bash"],t);case"markdown":case"md":return Ze(["html","jsx","bash"],t);default:return Ze(Object.keys(we),t)}}(a,l),c=n.split("\n"),s=Object.fromEntries(l.map((e=>[e.className,{start:0,range:""}]))),i=Object.fromEntries(l.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),m=Object.fromEntries(l.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),d=Object.fromEntries(l.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let p=0;p<c.length;){const e=c[p].match(o);if(!e){p+=1;continue}const t=e.slice(1).find((e=>void 0!==e));i[t]?s[i[t]].range+=p+",":m[t]?s[m[t]].start=p:d[t]&&(s[d[t]].range+=s[d[t]].start+"-"+(p-1)+","),c.splice(p,1)}n=c.join("\n");const u={};return Object.entries(s).forEach((e=>{let[t,{range:n}]=e;Ce()(n).forEach((e=>{null!=u[e]||(u[e]=[]),u[e].push(t)}))})),{lineClassNames:u,code:n}}const Be="codeBlockContainer_Ckt0";function Oe(e){let{as:t,...n}=e;const l=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[a,l]=e;const r=t[a];r&&"string"==typeof l&&(n[r]=l)})),n}(Ne());return a.createElement(t,(0,u.Z)({},n,{style:l,className:(0,m.Z)(n.className,Be,y.k.common.codeBlock)}))}const Ae={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function je(e){let{children:t,className:n}=e;return a.createElement(Oe,{as:"pre",tabIndex:0,className:(0,m.Z)(Ae.codeBlockStandalone,"thin-scrollbar",n)},a.createElement("code",{className:Ae.codeBlockLines},t))}const He={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Se(e,t){const[n,l]=(0,a.useState)(),o=(0,a.useCallback)((()=>{var t;l(null==(t=e.current)?void 0:t.closest("[role=tabpanel][hidden]"))}),[e,l]);(0,a.useEffect)((()=>{o()}),[o]),function(e,t,n){void 0===n&&(n=He);const l=(0,r.zX)(t),o=(0,r.Ql)(n);(0,a.useEffect)((()=>{const t=new MutationObserver(l);return e&&t.observe(e,o),()=>t.disconnect()}),[e,l,o])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),o())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}const Me={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]};var Pe={Prism:n(1205).Z,theme:Me};function Ie(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Ue(){return Ue=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},Ue.apply(this,arguments)}var ze=/\r\n|\r|\n/,Ve=function(e){0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},De=function(e,t){var n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)},Re=function(e,t){var n=e.plain,a=Object.create(null),l=e.styles.reduce((function(e,n){var a=n.languages,l=n.style;return a&&!a.includes(t)||n.types.forEach((function(t){var n=Ue({},e[t],l);e[t]=n})),e}),a);return l.root=n,l.plain=Ue({},n,{backgroundColor:null}),l};function We(e,t){var n={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&-1===t.indexOf(a)&&(n[a]=e[a]);return n}const Fe=function(e){function t(){for(var t=this,n=[],a=arguments.length;a--;)n[a]=arguments[a];e.apply(this,n),Ie(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?Re(e.theme,e.language):void 0;return t.themeDict=n})),Ie(this,"getLineProps",(function(e){var n=e.key,a=e.className,l=e.style,r=Ue({},We(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),o=t.getThemeDict(t.props);return void 0!==o&&(r.style=o.plain),void 0!==l&&(r.style=void 0!==r.style?Ue({},r.style,l):l),void 0!==n&&(r.key=n),a&&(r.className+=" "+a),r})),Ie(this,"getStyleForToken",(function(e){var n=e.types,a=e.empty,l=n.length,r=t.getThemeDict(t.props);if(void 0!==r){if(1===l&&"plain"===n[0])return a?{display:"inline-block"}:void 0;if(1===l&&!a)return r[n[0]];var o=a?{display:"inline-block"}:{},c=n.map((function(e){return r[e]}));return Object.assign.apply(Object,[o].concat(c))}})),Ie(this,"getTokenProps",(function(e){var n=e.key,a=e.className,l=e.style,r=e.token,o=Ue({},We(e,["key","className","style","token"]),{className:"token "+r.types.join(" "),children:r.content,style:t.getStyleForToken(r),key:void 0});return void 0!==l&&(o.style=void 0!==o.style?Ue({},o.style,l):l),void 0!==n&&(o.key=n),a&&(o.className+=" "+a),o})),Ie(this,"tokenize",(function(e,t,n,a){var l={code:t,grammar:n,language:a,tokens:[]};e.hooks.run("before-tokenize",l);var r=l.tokens=e.tokenize(l.code,l.grammar,l.language);return e.hooks.run("after-tokenize",l),r}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,a=e.code,l=e.children,r=this.getThemeDict(this.props),o=t.languages[n];return l({tokens:function(e){for(var t=[[]],n=[e],a=[0],l=[e.length],r=0,o=0,c=[],s=[c];o>-1;){for(;(r=a[o]++)<l[o];){var i=void 0,m=t[o],d=n[o][r];if("string"==typeof d?(m=o>0?m:["plain"],i=d):(m=De(m,d.type),d.alias&&(m=De(m,d.alias)),i=d.content),"string"==typeof i){var u=i.split(ze),p=u.length;c.push({types:m,content:u[0]});for(var f=1;f<p;f++)Ve(c),s.push(c=[]),c.push({types:m,content:u[f]})}else o++,t.push(m),n.push(i),a.push(0),l.push(i.length)}o--,t.pop(),n.pop(),a.pop(),l.pop()}return Ve(c),s}(void 0!==o?this.tokenize(t,a,o,n):[a]),className:"prism-code language-"+n,style:void 0!==r?r.root:{},getLineProps:this.getLineProps,getTokenProps:this.getTokenProps})},t}(a.Component),qe="codeLine_lJS_",Ge="codeLineNumber_Tfdd",Ye="codeLineContent_feaV";function $e(e){let{line:t,classNames:n,showLineNumbers:l,getLineProps:r,getTokenProps:o}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const c=r({line:t,className:(0,m.Z)(n,l&&qe)}),s=t.map(((e,t)=>a.createElement("span",(0,u.Z)({key:t},o({token:e,key:t})))));return a.createElement("span",c,l?a.createElement(a.Fragment,null,a.createElement("span",{className:Ge}),a.createElement("span",{className:Ye},s)):s,a.createElement("br",null))}function Je(e){return a.createElement("svg",(0,u.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"}))}function Qe(e){return a.createElement("svg",(0,u.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"}))}const Xe={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function Ke(e){let{code:t,className:n}=e;const[l,r]=(0,a.useState)(!1),o=(0,a.useRef)(void 0),c=(0,a.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;const a=document.createElement("textarea"),l=document.activeElement;a.value=e,a.setAttribute("readonly",""),a.style.contain="strict",a.style.position="absolute",a.style.left="-9999px",a.style.fontSize="12pt";const r=document.getSelection();let o=!1;r.rangeCount>0&&(o=r.getRangeAt(0)),n.append(a),a.select(),a.selectionStart=0,a.selectionEnd=e.length;let c=!1;try{c=document.execCommand("copy")}catch{}a.remove(),o&&(r.removeAllRanges(),r.addRange(o)),l&&l.focus()}(t),r(!0),o.current=window.setTimeout((()=>{r(!1)}),1e3)}),[t]);return(0,a.useEffect)((()=>()=>window.clearTimeout(o.current)),[]),a.createElement("button",{type:"button","aria-label":l?(0,p.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,p.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,p.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,m.Z)("clean-btn",n,Xe.copyButton,l&&Xe.copyButtonCopied),onClick:c},a.createElement("span",{className:Xe.copyButtonIcons,"aria-hidden":"true"},a.createElement(Je,{className:Xe.copyButtonIcon}),a.createElement(Qe,{className:Xe.copyButtonSuccessIcon})))}function et(e){return a.createElement("svg",(0,u.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"}))}const tt="wordWrapButtonIcon_Bwma",nt="wordWrapButtonEnabled_EoeP";function at(e){let{className:t,onClick:n,isEnabled:l}=e;const r=(0,p.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return a.createElement("button",{type:"button",onClick:n,className:(0,m.Z)("clean-btn",t,l&&nt),"aria-label":r,title:r},a.createElement(et,{className:tt,"aria-hidden":"true"}))}function lt(e){var t;let{children:n,className:l="",metastring:r,title:o,showLineNumbers:c,language:s}=e;const{prism:{defaultLanguage:i,magicComments:d}}=(0,G.L)(),p=null!=(t=null!=s?s:function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return null==t?void 0:t.replace(/language-/,"")}(l))?t:i,f=Ne(),h=function(){const[e,t]=(0,a.useState)(!1),[n,l]=(0,a.useState)(!1),r=(0,a.useRef)(null),o=(0,a.useCallback)((()=>{const n=r.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[r,e]),c=(0,a.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=r.current,n=e>t||r.current.querySelector("code").hasAttribute("style");l(n)}),[r]);return Se(r,c),(0,a.useEffect)((()=>{c()}),[e,c]),(0,a.useEffect)((()=>(window.addEventListener("resize",c,{passive:!0}),()=>{window.removeEventListener("resize",c)})),[c]),{codeBlockRef:r,isEnabled:e,isCodeScrollable:n,toggle:o}}(),v=function(e){var t,n;return null!=(t=null==e||null==(n=e.match(Te))?void 0:n.groups.title)?t:""}(r)||o,{lineClassNames:g,code:b}=xe(n,{metastring:r,language:p,magicComments:d}),E=null!=c?c:function(e){return Boolean(null==e?void 0:e.includes("showLineNumbers"))}(r);return a.createElement(Oe,{as:"div",className:(0,m.Z)(l,p&&!l.includes("language-"+p)&&"language-"+p)},v&&a.createElement("div",{className:Ae.codeBlockTitle},v),a.createElement("div",{className:Ae.codeBlockContent},a.createElement(Fe,(0,u.Z)({},Pe,{theme:f,code:b,language:null!=p?p:"text"}),(e=>{let{className:t,tokens:n,getLineProps:l,getTokenProps:r}=e;return a.createElement("pre",{tabIndex:0,ref:h.codeBlockRef,className:(0,m.Z)(t,Ae.codeBlock,"thin-scrollbar")},a.createElement("code",{className:(0,m.Z)(Ae.codeBlockLines,E&&Ae.codeBlockLinesWithNumbering)},n.map(((e,t)=>a.createElement($e,{key:t,line:e,getLineProps:l,getTokenProps:r,classNames:g[t],showLineNumbers:E})))))})),a.createElement("div",{className:Ae.buttonGroup},(h.isEnabled||h.isCodeScrollable)&&a.createElement(at,{className:Ae.codeButton,onClick:()=>h.toggle(),isEnabled:h.isEnabled}),a.createElement(Ke,{className:Ae.codeButton,code:b}))))}function rt(e){let{children:t,...n}=e;const l=(0,ye.Z)(),r=function(e){return a.Children.toArray(e).some((e=>(0,a.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),o="string"==typeof r?lt:je;return a.createElement(o,(0,u.Z)({key:String(l)},n),r)}var ot=n(7459);const ct="details_lb9f",st="isBrowser_bmU9",it="collapsibleContent_i85q";function mt(e){return!!e&&("SUMMARY"===e.tagName||mt(e.parentElement))}function dt(e,t){return!!e&&(e===t||dt(e.parentElement,t))}function ut(e){let{summary:t,children:n,...l}=e;const r=(0,ye.Z)(),o=(0,a.useRef)(null),{collapsed:c,setCollapsed:s}=(0,q.u)({initialState:!l.open}),[i,m]=(0,a.useState)(l.open),d=a.isValidElement(t)?t:a.createElement("summary",null,null!=t?t:"Details");return a.createElement("details",(0,u.Z)({},l,{ref:o,open:i,"data-collapsed":c,className:(0,ot.Z)(ct,r&&st,l.className),onMouseDown:e=>{mt(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;mt(t)&&dt(t,o.current)&&(e.preventDefault(),c?(s(!1),m(!0)):s(!0))}}),d,a.createElement(q.z,{lazy:!1,collapsed:c,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{s(e),m(!e)}},a.createElement("div",{className:it},n)))}const pt="details_b_Ee";function ft(e){let{...t}=e;return a.createElement(ut,(0,u.Z)({},t,{className:(0,m.Z)("alert alert--info",pt,t.className)}))}function ht(e){return a.createElement(ge,e)}const vt="containsTaskList_mC6p";function gt(e){if(void 0!==e)return(0,m.Z)(e,(null==e?void 0:e.includes("contains-task-list"))&&vt)}const bt="img_ev3q";const Et="admonition_LlT9",yt="admonitionHeading_tbUL",kt="admonitionIcon_kALy",Nt="admonitionContent_S0QG";const Lt={note:{infimaClassName:"secondary",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))},label:a.createElement(p.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)"},"note")},tip:{infimaClassName:"success",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"}))},label:a.createElement(p.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)"},"tip")},danger:{infimaClassName:"danger",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 12 16"},a.createElement("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))},label:a.createElement(p.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)"},"danger")},info:{infimaClassName:"info",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 14 16"},a.createElement("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))},label:a.createElement(p.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)"},"info")},caution:{infimaClassName:"warning",iconComponent:function(){return a.createElement("svg",{viewBox:"0 0 16 16"},a.createElement("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))},label:a.createElement(p.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)"},"caution")}},Ct={secondary:"note",important:"info",success:"tip",warning:"danger"};function Tt(e){var t;const{mdxAdmonitionTitle:n,rest:l}=function(e){const t=a.Children.toArray(e),n=t.find((e=>{var t;return a.isValidElement(e)&&"mdxAdmonitionTitle"===(null==(t=e.props)?void 0:t.mdxType)})),l=a.createElement(a.Fragment,null,t.filter((e=>e!==n)));return{mdxAdmonitionTitle:n,rest:l}}(e.children);return{...e,title:null!=(t=e.title)?t:n,children:l}}const _t={head:function(e){const t=a.Children.map(e.children,(e=>a.isValidElement(e)?function(e){var t;if(null!=(t=e.props)&&t.mdxType&&e.props.originalType){const{mdxType:t,originalType:n,...l}=e.props;return a.createElement(e.props.originalType,l)}return e}(e):e));return a.createElement(Ee.Z,e,t)},code:function(e){const t=["a","abbr","b","br","button","cite","code","del","dfn","em","i","img","input","ins","kbd","label","object","output","q","ruby","s","small","span","strong","sub","sup","time","u","var","wbr"];return a.Children.toArray(e.children).every((e=>{var n;return"string"==typeof e&&!e.includes("\n")||(0,a.isValidElement)(e)&&t.includes(null==(n=e.props)?void 0:n.mdxType)}))?a.createElement("code",e):a.createElement(rt,e)},a:function(e){return a.createElement(f.Z,e)},pre:function(e){var t;return a.createElement(rt,(0,a.isValidElement)(e.children)&&"code"===(null==(t=e.children.props)?void 0:t.originalType)?e.children.props:{...e})},details:function(e){const t=a.Children.toArray(e.children),n=t.find((e=>{var t;return a.isValidElement(e)&&"summary"===(null==(t=e.props)?void 0:t.mdxType)})),l=a.createElement(a.Fragment,null,t.filter((e=>e!==n)));return a.createElement(ft,(0,u.Z)({},e,{summary:n}),l)},ul:function(e){return a.createElement("ul",(0,u.Z)({},e,{className:gt(e.className)}))},img:function(e){return a.createElement("img",(0,u.Z)({loading:"lazy"},e,{className:(t=e.className,(0,m.Z)(t,bt))}));var t},h1:e=>a.createElement(ht,(0,u.Z)({as:"h1"},e)),h2:e=>a.createElement(ht,(0,u.Z)({as:"h2"},e)),h3:e=>a.createElement(ht,(0,u.Z)({as:"h3"},e)),h4:e=>a.createElement(ht,(0,u.Z)({as:"h4"},e)),h5:e=>a.createElement(ht,(0,u.Z)({as:"h5"},e)),h6:e=>a.createElement(ht,(0,u.Z)({as:"h6"},e)),admonition:function(e){const{children:t,type:n,title:l,icon:r}=Tt(e),o=function(e){var t;const n=null!=(t=Ct[e])?t:e;return Lt[n]||(console.warn('No admonition config found for admonition type "'+n+'". Using Info as fallback.'),Lt.info)}(n),c=null!=l?l:o.label,{iconComponent:s}=o,i=null!=r?r:a.createElement(s,null);return a.createElement("div",{className:(0,m.Z)(y.k.common.admonition,y.k.common.admonitionType(e.type),"alert","alert--"+o.infimaClassName,Et)},a.createElement("div",{className:yt},a.createElement("span",{className:kt},i),c),a.createElement("div",{className:Nt},t))},mermaid:()=>null};function wt(e){let{children:t}=e;return a.createElement(be.Zo,{components:_t},t)}function Zt(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=s();return t.hide_title||void 0!==n?null:e.title}();return a.createElement("div",{className:(0,m.Z)(y.k.docs.docMarkdown,"markdown")},n&&a.createElement("header",null,a.createElement(ge,{as:"h1"},n)),a.createElement(wt,null,t))}var xt=n(2802),Bt=n(8596),Ot=n(4996);function At(e){return a.createElement("svg",(0,u.Z)({viewBox:"0 0 24 24"},e),a.createElement("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"}))}const jt="breadcrumbHomeIcon_YNFT";function Ht(){const e=(0,Ot.Z)("/");return a.createElement("li",{className:"breadcrumbs__item"},a.createElement(f.Z,{"aria-label":(0,p.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e},a.createElement(At,{className:jt})))}const St="breadcrumbsContainer_Z_bl";function Mt(e){let{children:t,href:n,isLast:l}=e;const r="breadcrumbs__link";return l?a.createElement("span",{className:r,itemProp:"name"},t):n?a.createElement(f.Z,{className:r,href:n,itemProp:"item"},a.createElement("span",{itemProp:"name"},t)):a.createElement("span",{className:r},t)}function Pt(e){let{children:t,active:n,index:l,addMicrodata:r}=e;return a.createElement("li",(0,u.Z)({},r&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},{className:(0,m.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n})}),t,a.createElement("meta",{itemProp:"position",content:String(l+1)}))}function It(){const e=(0,xt.s1)(),t=(0,Bt.Ns)();return e?a.createElement("nav",{className:(0,m.Z)(y.k.docs.docBreadcrumbs,St),"aria-label":(0,p.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"})},a.createElement("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList"},t&&a.createElement(Ht,null),e.map(((t,n)=>{const l=n===e.length-1;return a.createElement(Pt,{key:n,active:l,index:n,addMicrodata:!!t.href},a.createElement(Mt,{href:t.href,isLast:l},t.label))})))):null}const Ut="docItemContainer_Djhp",zt="docItemCol_VOVn";function Vt(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=s(),n=(0,d.i)(),l=e.hide_table_of_contents,r=!l&&t.length>0;return{hidden:l,mobile:r?a.createElement(de,null):void 0,desktop:!r||"desktop"!==n&&"ssr"!==n?void 0:a.createElement(fe,null)}}();return a.createElement("div",{className:"row"},a.createElement("div",{className:(0,m.Z)("col",!n.hidden&&zt)},a.createElement(w,null),a.createElement("div",{className:Ut},a.createElement("article",null,a.createElement(It,null),a.createElement(Z,null),n.mobile,a.createElement(Zt,null,t),a.createElement(F,null)),a.createElement(g,null))),n.desktop&&a.createElement("div",{className:"col col--3"},n.desktop))}function Dt(e){const t="docs-doc-id-"+e.content.metadata.unversionedId,n=e.content;return a.createElement(c,{content:e.content},a.createElement(l.FG,{className:t},a.createElement(i,null),a.createElement(Vt,null,a.createElement(n,null))))}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>c,q:()=>o});var a=n(7294),l=n(902);const r=a.createContext(null);function o(e){let{children:t,version:n}=e;return a.createElement(r.Provider,{value:n},t)}function c(){const e=(0,a.useContext)(r);if(null===e)throw new l.i6("DocsVersionProvider");return e}},7594:(e,t)=>{function n(e){let t,n=[];for(let a of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(a))n.push(parseInt(a,10));else if(t=a.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,a,l,r]=t;if(a&&r){a=parseInt(a),r=parseInt(r);const e=a<r?1:-1;"-"!==l&&".."!==l&&"\u2025"!==l||(r+=e);for(let t=a;t!==r;t+=e)n.push(t)}}return n}t.default=n,e.exports=n}}]); \ No newline at end of file diff --git a/docs/assets/js/17896441.6d94e406.js b/docs/assets/js/17896441.6d94e406.js new file mode 100644 index 0000000000..d2d3a0e21b --- /dev/null +++ b/docs/assets/js/17896441.6d94e406.js @@ -0,0 +1 @@ +(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7918],{9413:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>Wt});var s=n(7294),a=n(833),o=n(902),i=n(5893);const l=s.createContext(null);function c(e){let{children:t,content:n}=e;const a=function(e){return(0,s.useMemo)((()=>({metadata:e.metadata,frontMatter:e.frontMatter,assets:e.assets,contentTitle:e.contentTitle,toc:e.toc})),[e])}(n);return(0,i.jsx)(l.Provider,{value:a,children:t})}function r(){const e=(0,s.useContext)(l);if(null===e)throw new o.i6("DocProvider");return e}function d(){const{metadata:e,frontMatter:t,assets:n}=r();return(0,i.jsx)(a.d,{title:e.title,description:e.description,keywords:t.keywords,image:n.image??t.image})}var u=n(512),m=n(7524),h=n(5999),p=n(3692);function f(e){const{permalink:t,title:n,subLabel:s,isNext:a}=e;return(0,i.jsxs)(p.Z,{className:(0,u.Z)("pagination-nav__link",a?"pagination-nav__link--next":"pagination-nav__link--prev"),to:t,children:[s&&(0,i.jsx)("div",{className:"pagination-nav__sublabel",children:s}),(0,i.jsx)("div",{className:"pagination-nav__label",children:n})]})}function x(e){const{previous:t,next:n}=e;return(0,i.jsxs)("nav",{className:"pagination-nav docusaurus-mt-lg","aria-label":(0,h.I)({id:"theme.docs.paginator.navAriaLabel",message:"Docs pages",description:"The ARIA label for the docs pagination"}),children:[t&&(0,i.jsx)(f,{...t,subLabel:(0,i.jsx)(h.Z,{id:"theme.docs.paginator.previous",description:"The label used to navigate to the previous doc",children:"Previous"})}),n&&(0,i.jsx)(f,{...n,subLabel:(0,i.jsx)(h.Z,{id:"theme.docs.paginator.next",description:"The label used to navigate to the next doc",children:"Next"}),isNext:!0})]})}function b(){const{metadata:e}=r();return(0,i.jsx)(x,{previous:e.previous,next:e.next})}var g=n(2263),j=n(143),v=n(5281),N=n(373),C=n(4477);const k={unreleased:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,i.jsx)(h.Z,{id:"theme.docs.versions.unreleasedVersionLabel",description:"The label used to tell the user that he's browsing an unreleased doc version",values:{siteTitle:t,versionLabel:(0,i.jsx)("b",{children:n.label})},children:"This is unreleased documentation for {siteTitle} {versionLabel} version."})},unmaintained:function(e){let{siteTitle:t,versionMetadata:n}=e;return(0,i.jsx)(h.Z,{id:"theme.docs.versions.unmaintainedVersionLabel",description:"The label used to tell the user that he's browsing an unmaintained doc version",values:{siteTitle:t,versionLabel:(0,i.jsx)("b",{children:n.label})},children:"This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained."})}};function L(e){const t=k[e.versionMetadata.banner];return(0,i.jsx)(t,{...e})}function y(e){let{versionLabel:t,to:n,onClick:s}=e;return(0,i.jsx)(h.Z,{id:"theme.docs.versions.latestVersionSuggestionLabel",description:"The label used to tell the user to check the latest version",values:{versionLabel:t,latestVersionLink:(0,i.jsx)("b",{children:(0,i.jsx)(p.Z,{to:n,onClick:s,children:(0,i.jsx)(h.Z,{id:"theme.docs.versions.latestVersionLinkLabel",description:"The label used for the latest version suggestion link label",children:"latest version"})})})},children:"For up-to-date documentation, see the {latestVersionLink} ({versionLabel})."})}function B(e){let{className:t,versionMetadata:n}=e;const{siteConfig:{title:s}}=(0,g.Z)(),{pluginId:a}=(0,j.gA)({failfast:!0}),{savePreferredVersionName:o}=(0,N.J)(a),{latestDocSuggestion:l,latestVersionSuggestion:c}=(0,j.Jo)(a),r=l??(d=c).docs.find((e=>e.id===d.mainDocId));var d;return(0,i.jsxs)("div",{className:(0,u.Z)(t,v.k.docs.docVersionBanner,"alert alert--warning margin-bottom--md"),role:"alert",children:[(0,i.jsx)("div",{children:(0,i.jsx)(L,{siteTitle:s,versionMetadata:n})}),(0,i.jsx)("div",{className:"margin-top--md",children:(0,i.jsx)(y,{versionLabel:c.label,to:r.path,onClick:()=>o(c.name)})})]})}function _(e){let{className:t}=e;const n=(0,C.E)();return n.banner?(0,i.jsx)(B,{className:t,versionMetadata:n}):null}function w(e){let{className:t}=e;const n=(0,C.E)();return n.badge?(0,i.jsx)("span",{className:(0,u.Z)(t,v.k.docs.docVersionBadge,"badge badge--secondary"),children:(0,i.jsx)(h.Z,{id:"theme.docs.versionBadge.label",values:{versionLabel:n.label},children:"Version: {versionLabel}"})}):null}function Z(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n}=e;return(0,i.jsx)(h.Z,{id:"theme.lastUpdated.atDate",description:"The words used to describe on which date a page has been last updated",values:{date:(0,i.jsx)("b",{children:(0,i.jsx)("time",{dateTime:new Date(1e3*t).toISOString(),children:n})})},children:" on {date}"})}function T(e){let{lastUpdatedBy:t}=e;return(0,i.jsx)(h.Z,{id:"theme.lastUpdated.byUser",description:"The words used to describe by who the page has been last updated",values:{user:(0,i.jsx)("b",{children:t})},children:" by {user}"})}function E(e){let{lastUpdatedAt:t,formattedLastUpdatedAt:n,lastUpdatedBy:s}=e;return(0,i.jsxs)("span",{className:v.k.common.lastUpdated,children:[(0,i.jsx)(h.Z,{id:"theme.lastUpdated.lastUpdatedAtBy",description:"The sentence used to display when a page has been last updated, and by who",values:{atDate:t&&n?(0,i.jsx)(Z,{lastUpdatedAt:t,formattedLastUpdatedAt:n}):"",byUser:s?(0,i.jsx)(T,{lastUpdatedBy:s}):""},children:"Last updated{atDate}{byUser}"}),!1]})}const H={iconEdit:"iconEdit_Z9Sw"};function A(e){let{className:t,...n}=e;return(0,i.jsx)("svg",{fill:"currentColor",height:"20",width:"20",viewBox:"0 0 40 40",className:(0,u.Z)(H.iconEdit,t),"aria-hidden":"true",...n,children:(0,i.jsx)("g",{children:(0,i.jsx)("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})})})}function I(e){let{editUrl:t}=e;return(0,i.jsxs)(p.Z,{to:t,className:v.k.common.editThisPage,children:[(0,i.jsx)(A,{}),(0,i.jsx)(h.Z,{id:"theme.common.editThisPage",description:"The link label to edit the current page",children:"Edit this page"})]})}const M={tag:"tag_zVej",tagRegular:"tagRegular_sFm0",tagWithCount:"tagWithCount_h2kH"};function S(e){let{permalink:t,label:n,count:s}=e;return(0,i.jsxs)(p.Z,{href:t,className:(0,u.Z)(M.tag,s?M.tagWithCount:M.tagRegular),children:[n,s&&(0,i.jsx)("span",{children:s})]})}const U={tags:"tags_jXut",tag:"tag_QGVx"};function z(e){let{tags:t}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("b",{children:(0,i.jsx)(h.Z,{id:"theme.tags.tagsListLabel",description:"The label alongside a tag list",children:"Tags:"})}),(0,i.jsx)("ul",{className:(0,u.Z)(U.tags,"padding--none","margin-left--sm"),children:t.map((e=>{let{label:t,permalink:n}=e;return(0,i.jsx)("li",{className:U.tag,children:(0,i.jsx)(S,{label:t,permalink:n})},n)}))})]})}const V={lastUpdated:"lastUpdated_vwxv"};function R(e){return(0,i.jsx)("div",{className:(0,u.Z)(v.k.docs.docFooterTagsRow,"row margin-bottom--sm"),children:(0,i.jsx)("div",{className:"col",children:(0,i.jsx)(z,{...e})})})}function O(e){let{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:s,formattedLastUpdatedAt:a}=e;return(0,i.jsxs)("div",{className:(0,u.Z)(v.k.docs.docFooterEditMetaRow,"row"),children:[(0,i.jsx)("div",{className:"col",children:t&&(0,i.jsx)(I,{editUrl:t})}),(0,i.jsx)("div",{className:(0,u.Z)("col",V.lastUpdated),children:(n||s)&&(0,i.jsx)(E,{lastUpdatedAt:n,formattedLastUpdatedAt:a,lastUpdatedBy:s})})]})}function P(){const{metadata:e}=r(),{editUrl:t,lastUpdatedAt:n,formattedLastUpdatedAt:s,lastUpdatedBy:a,tags:o}=e,l=o.length>0,c=!!(t||n||a);return l||c?(0,i.jsxs)("footer",{className:(0,u.Z)(v.k.docs.docFooter,"docusaurus-mt-lg"),children:[l&&(0,i.jsx)(R,{tags:o}),c&&(0,i.jsx)(O,{editUrl:t,lastUpdatedAt:n,lastUpdatedBy:a,formattedLastUpdatedAt:s})]}):null}var $=n(6043),D=n(6668);function W(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const s=n.slice(2,e.level);e.parentIndex=Math.max(...s),n[e.level]=t}));const s=[];return t.forEach((e=>{const{parentIndex:n,...a}=e;n>=0?t[n].children.push(a):s.push(a)})),s}function F(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:s}=e;return t.flatMap((e=>{const t=F({toc:e.children,minHeadingLevel:n,maxHeadingLevel:s});return function(e){return e.level>=n&&e.level<=s}(e)?[{...e,children:t}]:t}))}function q(e){const t=e.getBoundingClientRect();return t.top===t.bottom?q(e.parentNode):t}function G(e,t){let{anchorTopOffset:n}=t;const s=e.find((e=>q(e).top>=n));if(s){return function(e){return e.top>0&&e.bottom<window.innerHeight/2}(q(s))?s:e[e.indexOf(s)-1]??null}return e[e.length-1]??null}function J(){const e=(0,s.useRef)(0),{navbar:{hideOnScroll:t}}=(0,D.L)();return(0,s.useEffect)((()=>{e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function Y(e){const t=(0,s.useRef)(void 0),n=J();(0,s.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:s,linkActiveClassName:a,minHeadingLevel:o,maxHeadingLevel:i}=e;function l(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(s),l=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const s=[];for(let a=t;a<=n;a+=1)s.push(`h${a}.anchor`);return Array.from(document.querySelectorAll(s.join()))}({minHeadingLevel:o,maxHeadingLevel:i}),c=G(l,{anchorTopOffset:n.current}),r=e.find((e=>c&&c.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(a),e.classList.add(a),t.current=e):e.classList.remove(a)}(e,e===r)}))}return document.addEventListener("scroll",l),document.addEventListener("resize",l),l(),()=>{document.removeEventListener("scroll",l),document.removeEventListener("resize",l)}}),[e,n])}function Q(e){let{toc:t,className:n,linkClassName:s,isChild:a}=e;return t.length?(0,i.jsx)("ul",{className:a?void 0:n,children:t.map((e=>(0,i.jsxs)("li",{children:[(0,i.jsx)(p.Z,{to:`#${e.id}`,className:s??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,i.jsx)(Q,{isChild:!0,toc:e.children,className:n,linkClassName:s})]},e.id)))}):null}const X=s.memo(Q);function K(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:a="table-of-contents__link",linkActiveClassName:o,minHeadingLevel:l,maxHeadingLevel:c,...r}=e;const d=(0,D.L)(),u=l??d.tableOfContents.minHeadingLevel,m=c??d.tableOfContents.maxHeadingLevel,h=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:a}=e;return(0,s.useMemo)((()=>F({toc:W(t),minHeadingLevel:n,maxHeadingLevel:a})),[t,n,a])}({toc:t,minHeadingLevel:u,maxHeadingLevel:m});return Y((0,s.useMemo)((()=>{if(a&&o)return{linkClassName:a,linkActiveClassName:o,minHeadingLevel:u,maxHeadingLevel:m}}),[a,o,u,m])),(0,i.jsx)(X,{toc:h,className:n,linkClassName:a,...r})}const ee={tocCollapsibleButton:"tocCollapsibleButton_TO0P",tocCollapsibleButtonExpanded:"tocCollapsibleButtonExpanded_MG3E"};function te(e){let{collapsed:t,...n}=e;return(0,i.jsx)("button",{type:"button",...n,className:(0,u.Z)("clean-btn",ee.tocCollapsibleButton,!t&&ee.tocCollapsibleButtonExpanded,n.className),children:(0,i.jsx)(h.Z,{id:"theme.TOCCollapsible.toggleButtonLabel",description:"The label used by the button on the collapsible TOC component",children:"On this page"})})}const ne={tocCollapsible:"tocCollapsible_ETCw",tocCollapsibleContent:"tocCollapsibleContent_vkbj",tocCollapsibleExpanded:"tocCollapsibleExpanded_sAul"};function se(e){let{toc:t,className:n,minHeadingLevel:s,maxHeadingLevel:a}=e;const{collapsed:o,toggleCollapsed:l}=(0,$.u)({initialState:!0});return(0,i.jsxs)("div",{className:(0,u.Z)(ne.tocCollapsible,!o&&ne.tocCollapsibleExpanded,n),children:[(0,i.jsx)(te,{collapsed:o,onClick:l}),(0,i.jsx)($.z,{lazy:!0,className:ne.tocCollapsibleContent,collapsed:o,children:(0,i.jsx)(K,{toc:t,minHeadingLevel:s,maxHeadingLevel:a})})]})}const ae={tocMobile:"tocMobile_ITEo"};function oe(){const{toc:e,frontMatter:t}=r();return(0,i.jsx)(se,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:(0,u.Z)(v.k.docs.docTocMobile,ae.tocMobile)})}const ie={tableOfContents:"tableOfContents_bqdL",docItemContainer:"docItemContainer_F8PC"},le="table-of-contents__link toc-highlight",ce="table-of-contents__link--active";function re(e){let{className:t,...n}=e;return(0,i.jsx)("div",{className:(0,u.Z)(ie.tableOfContents,"thin-scrollbar",t),children:(0,i.jsx)(K,{...n,linkClassName:le,linkActiveClassName:ce})})}function de(){const{toc:e,frontMatter:t}=r();return(0,i.jsx)(re,{toc:e,minHeadingLevel:t.toc_min_heading_level,maxHeadingLevel:t.toc_max_heading_level,className:v.k.docs.docTocDesktop})}var ue=n(2503),me=n(1151),he=n(5742),pe=n(2389),fe=n(2949);function xe(){const{prism:e}=(0,D.L)(),{colorMode:t}=(0,fe.I)(),n=e.theme,s=e.darkTheme||n;return"dark"===t?s:n}var be=n(7594),ge=n.n(be);const je=/title=(?<quote>["'])(?<title>.*?)\1/,ve=/\{(?<range>[\d,-]+)\}/,Ne={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},Ce={...Ne,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},ke=Object.keys(Ne);function Le(e,t){const n=e.map((e=>{const{start:n,end:s}=Ce[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${s})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function ye(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:a,metastring:o}=t;if(o&&ve.test(o)){const e=o.match(ve).groups.range;if(0===a.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${o}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=a[0].className,s=ge()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const i=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return Le(["js","jsBlock"],t);case"jsx":case"tsx":return Le(["js","jsBlock","jsx"],t);case"html":return Le(["js","jsBlock","html"],t);case"python":case"py":case"bash":return Le(["bash"],t);case"markdown":case"md":return Le(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return Le(["tex"],t);case"lua":case"haskell":case"sql":return Le(["lua"],t);case"wasm":return Le(["wasm"],t);case"vb":case"vbnet":case"vba":case"visual-basic":return Le(["vb","rem"],t);case"batch":return Le(["rem"],t);case"basic":return Le(["rem","f90"],t);case"fsharp":return Le(["js","ml"],t);case"ocaml":case"sml":return Le(["ml"],t);case"fortran":return Le(["f90"],t);case"cobol":return Le(["cobol"],t);default:return Le(ke,t)}}(s,a),l=n.split("\n"),c=Object.fromEntries(a.map((e=>[e.className,{start:0,range:""}]))),r=Object.fromEntries(a.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(a.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let h=0;h<l.length;){const e=l[h].match(i);if(!e){h+=1;continue}const t=e.slice(1).find((e=>void 0!==e));r[t]?c[r[t]].range+=`${h},`:d[t]?c[d[t]].start=h:u[t]&&(c[u[t]].range+=`${c[u[t]].start}-${h-1},`),l.splice(h,1)}n=l.join("\n");const m={};return Object.entries(c).forEach((e=>{let[t,{range:n}]=e;ge()(n).forEach((e=>{m[e]??=[],m[e].push(t)}))})),{lineClassNames:m,code:n}}const Be={codeBlockContainer:"codeBlockContainer_Ckt0"};function _e(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,a]=e;const o=t[s];o&&"string"==typeof a&&(n[o]=a)})),n}(xe());return(0,i.jsx)(t,{...n,style:s,className:(0,u.Z)(n.className,Be.codeBlockContainer,v.k.common.codeBlock)})}const we={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function Ze(e){let{children:t,className:n}=e;return(0,i.jsx)(_e,{as:"pre",tabIndex:0,className:(0,u.Z)(we.codeBlockStandalone,"thin-scrollbar",n),children:(0,i.jsx)("code",{className:we.codeBlockLines,children:t})})}const Te={attributes:!0,characterData:!0,childList:!0,subtree:!0};function Ee(e,t){const[n,a]=(0,s.useState)(),i=(0,s.useCallback)((()=>{a(e.current?.closest("[role=tabpanel][hidden]"))}),[e,a]);(0,s.useEffect)((()=>{i()}),[i]),function(e,t,n){void 0===n&&(n=Te);const a=(0,o.zX)(t),i=(0,o.Ql)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(a);return e&&t.observe(e,i),()=>t.disconnect()}),[e,a,i])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),i())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var He=n(2573);const Ae={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function Ie(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:a,getTokenProps:o}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const l=a({line:t,className:(0,u.Z)(n,s&&Ae.codeLine)}),c=t.map(((e,t)=>(0,i.jsx)("span",{...o({token:e,key:t})},t)));return(0,i.jsxs)("span",{...l,children:[s?(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("span",{className:Ae.codeLineNumber}),(0,i.jsx)("span",{className:Ae.codeLineContent,children:c})]}):c,(0,i.jsx)("br",{})]})}function Me(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function Se(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const Ue={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function ze(e){let{code:t,className:n}=e;const[a,o]=(0,s.useState)(!1),l=(0,s.useRef)(void 0),c=(0,s.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const s=document.createElement("textarea"),a=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const o=document.getSelection(),i=o.rangeCount>0&&o.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch{}s.remove(),i&&(o.removeAllRanges(),o.addRange(i)),a&&a.focus()}(t),o(!0),l.current=window.setTimeout((()=>{o(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(l.current)),[]),(0,i.jsx)("button",{type:"button","aria-label":a?(0,h.I)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,h.I)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,h.I)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,u.Z)("clean-btn",n,Ue.copyButton,a&&Ue.copyButtonCopied),onClick:c,children:(0,i.jsxs)("span",{className:Ue.copyButtonIcons,"aria-hidden":"true",children:[(0,i.jsx)(Me,{className:Ue.copyButtonIcon}),(0,i.jsx)(Se,{className:Ue.copyButtonSuccessIcon})]})})}function Ve(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}const Re={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function Oe(e){let{className:t,onClick:n,isEnabled:s}=e;const a=(0,h.I)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,i.jsx)("button",{type:"button",onClick:n,className:(0,u.Z)("clean-btn",t,s&&Re.wordWrapButtonEnabled),"aria-label":a,title:a,children:(0,i.jsx)(Ve,{className:Re.wordWrapButtonIcon,"aria-hidden":"true"})})}function Pe(e){let{children:t,className:n="",metastring:a,title:o,showLineNumbers:l,language:c}=e;const{prism:{defaultLanguage:r,magicComments:d}}=(0,D.L)(),m=function(e){return e?.toLowerCase()}(c??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??r),h=xe(),p=function(){const[e,t]=(0,s.useState)(!1),[n,a]=(0,s.useState)(!1),o=(0,s.useRef)(null),i=(0,s.useCallback)((()=>{const n=o.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[o,e]),l=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=o.current,n=e>t||o.current.querySelector("code").hasAttribute("style");a(n)}),[o]);return Ee(o,l),(0,s.useEffect)((()=>{l()}),[e,l]),(0,s.useEffect)((()=>(window.addEventListener("resize",l,{passive:!0}),()=>{window.removeEventListener("resize",l)})),[l]),{codeBlockRef:o,isEnabled:e,isCodeScrollable:n,toggle:i}}(),f=function(e){return e?.match(je)?.groups.title??""}(a)||o,{lineClassNames:x,code:b}=ye(t,{metastring:a,language:m,magicComments:d}),g=l??function(e){return Boolean(e?.includes("showLineNumbers"))}(a);return(0,i.jsxs)(_e,{as:"div",className:(0,u.Z)(n,m&&!n.includes(`language-${m}`)&&`language-${m}`),children:[f&&(0,i.jsx)("div",{className:we.codeBlockTitle,children:f}),(0,i.jsxs)("div",{className:we.codeBlockContent,children:[(0,i.jsx)(He.y$,{theme:h,code:b,language:m??"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:a,getTokenProps:o}=e;return(0,i.jsx)("pre",{tabIndex:0,ref:p.codeBlockRef,className:(0,u.Z)(t,we.codeBlock,"thin-scrollbar"),style:n,children:(0,i.jsx)("code",{className:(0,u.Z)(we.codeBlockLines,g&&we.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,i.jsx)(Ie,{line:e,getLineProps:a,getTokenProps:o,classNames:x[t],showLineNumbers:g},t)))})})}}),(0,i.jsxs)("div",{className:we.buttonGroup,children:[(p.isEnabled||p.isCodeScrollable)&&(0,i.jsx)(Oe,{className:we.codeButton,onClick:()=>p.toggle(),isEnabled:p.isEnabled}),(0,i.jsx)(ze,{className:we.codeButton,code:b})]})]})]})}function $e(e){let{children:t,...n}=e;const a=(0,pe.Z)(),o=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),l="string"==typeof o?Pe:Ze;return(0,i.jsx)(l,{...n,children:o},String(a))}function De(e){return(0,i.jsx)("code",{...e})}const We={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function Fe(e){return!!e&&("SUMMARY"===e.tagName||Fe(e.parentElement))}function qe(e,t){return!!e&&(e===t||qe(e.parentElement,t))}function Ge(e){let{summary:t,children:n,...a}=e;const o=(0,pe.Z)(),l=(0,s.useRef)(null),{collapsed:c,setCollapsed:r}=(0,$.u)({initialState:!a.open}),[d,m]=(0,s.useState)(a.open),h=s.isValidElement(t)?t:(0,i.jsx)("summary",{children:t??"Details"});return(0,i.jsxs)("details",{...a,ref:l,open:d,"data-collapsed":c,className:(0,u.Z)(We.details,o&&We.isBrowser,a.className),onMouseDown:e=>{Fe(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;Fe(t)&&qe(t,l.current)&&(e.preventDefault(),c?(r(!1),m(!0)):r(!0))},children:[h,(0,i.jsx)($.z,{lazy:!1,collapsed:c,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{r(e),m(!e)},children:(0,i.jsx)("div",{className:We.collapsibleContent,children:n})})]})}const Je={details:"details_b_Ee"},Ye="alert alert--info";function Qe(e){let{...t}=e;return(0,i.jsx)(Ge,{...t,className:(0,u.Z)(Ye,Je.details,t.className)})}function Xe(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),a=(0,i.jsx)(i.Fragment,{children:t.filter((e=>e!==n))});return(0,i.jsx)(Qe,{...e,summary:n,children:a})}function Ke(e){return(0,i.jsx)(ue.Z,{...e})}const et={containsTaskList:"containsTaskList_mC6p"};function tt(e){if(void 0!==e)return(0,u.Z)(e,e?.includes("contains-task-list")&&et.containsTaskList)}const nt={img:"img_ev3q"};function st(e){const{mdxAdmonitionTitle:t,rest:n}=function(e){const t=s.Children.toArray(e),n=t.find((e=>s.isValidElement(e)&&"mdxAdmonitionTitle"===e.type)),a=t.filter((e=>e!==n)),o=n?.props.children;return{mdxAdmonitionTitle:o,rest:a.length>0?(0,i.jsx)(i.Fragment,{children:a}):null}}(e.children),a=e.title??t;return{...e,...a&&{title:a},children:n}}const at={admonition:"admonition_xJq3",admonitionHeading:"admonitionHeading_Gvgb",admonitionIcon:"admonitionIcon_Rf37",admonitionContent:"admonitionContent_BuS1"};function ot(e){let{type:t,className:n,children:s}=e;return(0,i.jsx)("div",{className:(0,u.Z)(v.k.common.admonition,v.k.common.admonitionType(t),at.admonition,n),children:s})}function it(e){let{icon:t,title:n}=e;return(0,i.jsxs)("div",{className:at.admonitionHeading,children:[(0,i.jsx)("span",{className:at.admonitionIcon,children:t}),n]})}function lt(e){let{children:t}=e;return t?(0,i.jsx)("div",{className:at.admonitionContent,children:t}):null}function ct(e){const{type:t,icon:n,title:s,children:a,className:o}=e;return(0,i.jsxs)(ot,{type:t,className:o,children:[(0,i.jsx)(it,{title:s,icon:n}),(0,i.jsx)(lt,{children:a})]})}function rt(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})})}const dt={icon:(0,i.jsx)(rt,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.note",description:"The default label used for the Note admonition (:::note)",children:"note"})};function ut(e){return(0,i.jsx)(ct,{...dt,...e,className:(0,u.Z)("alert alert--secondary",e.className),children:e.children})}function mt(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"})})}const ht={icon:(0,i.jsx)(mt,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.tip",description:"The default label used for the Tip admonition (:::tip)",children:"tip"})};function pt(e){return(0,i.jsx)(ct,{...ht,...e,className:(0,u.Z)("alert alert--success",e.className),children:e.children})}function ft(e){return(0,i.jsx)("svg",{viewBox:"0 0 14 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"})})}const xt={icon:(0,i.jsx)(ft,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.info",description:"The default label used for the Info admonition (:::info)",children:"info"})};function bt(e){return(0,i.jsx)(ct,{...xt,...e,className:(0,u.Z)("alert alert--info",e.className),children:e.children})}function gt(e){return(0,i.jsx)("svg",{viewBox:"0 0 16 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"})})}const jt={icon:(0,i.jsx)(gt,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.warning",description:"The default label used for the Warning admonition (:::warning)",children:"warning"})};function vt(e){return(0,i.jsx)("svg",{viewBox:"0 0 12 16",...e,children:(0,i.jsx)("path",{fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"})})}const Nt={icon:(0,i.jsx)(vt,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.danger",description:"The default label used for the Danger admonition (:::danger)",children:"danger"})};const Ct={icon:(0,i.jsx)(gt,{}),title:(0,i.jsx)(h.Z,{id:"theme.admonition.caution",description:"The default label used for the Caution admonition (:::caution)",children:"caution"})};const kt={...{note:ut,tip:pt,info:bt,warning:function(e){return(0,i.jsx)(ct,{...jt,...e,className:(0,u.Z)("alert alert--warning",e.className),children:e.children})},danger:function(e){return(0,i.jsx)(ct,{...Nt,...e,className:(0,u.Z)("alert alert--danger",e.className),children:e.children})}},...{secondary:e=>(0,i.jsx)(ut,{title:"secondary",...e}),important:e=>(0,i.jsx)(bt,{title:"important",...e}),success:e=>(0,i.jsx)(pt,{title:"success",...e}),caution:function(e){return(0,i.jsx)(ct,{...Ct,...e,className:(0,u.Z)("alert alert--warning",e.className),children:e.children})}}};function Lt(e){const t=st(e),n=(s=t.type,kt[s]||(console.warn(`No admonition component found for admonition type "${s}". Using Info as fallback.`),kt.info));var s;return(0,i.jsx)(n,{...t})}const yt={Head:he.Z,details:Xe,Details:Xe,code:function(e){return function(e){return void 0!==e.children&&s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))}(e)?(0,i.jsx)(De,{...e}):(0,i.jsx)($e,{...e})},a:function(e){return(0,i.jsx)(p.Z,{...e})},pre:function(e){return(0,i.jsx)(i.Fragment,{children:e.children})},ul:function(e){return(0,i.jsx)("ul",{...e,className:tt(e.className)})},img:function(e){return(0,i.jsx)("img",{loading:"lazy",...e,className:(t=e.className,(0,u.Z)(t,nt.img))});var t},h1:e=>(0,i.jsx)(Ke,{as:"h1",...e}),h2:e=>(0,i.jsx)(Ke,{as:"h2",...e}),h3:e=>(0,i.jsx)(Ke,{as:"h3",...e}),h4:e=>(0,i.jsx)(Ke,{as:"h4",...e}),h5:e=>(0,i.jsx)(Ke,{as:"h5",...e}),h6:e=>(0,i.jsx)(Ke,{as:"h6",...e}),admonition:Lt,mermaid:()=>null};function Bt(e){let{children:t}=e;return(0,i.jsx)(me.Z,{components:yt,children:t})}function _t(e){let{children:t}=e;const n=function(){const{metadata:e,frontMatter:t,contentTitle:n}=r();return t.hide_title||void 0!==n?null:e.title}();return(0,i.jsxs)("div",{className:(0,u.Z)(v.k.docs.docMarkdown,"markdown"),children:[n&&(0,i.jsx)("header",{children:(0,i.jsx)(ue.Z,{as:"h1",children:n})}),(0,i.jsx)(Bt,{children:t})]})}var wt=n(2802),Zt=n(8596),Tt=n(4996);function Et(e){return(0,i.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,i.jsx)("path",{d:"M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z",fill:"currentColor"})})}const Ht={breadcrumbHomeIcon:"breadcrumbHomeIcon_YNFT"};function At(){const e=(0,Tt.Z)("/");return(0,i.jsx)("li",{className:"breadcrumbs__item",children:(0,i.jsx)(p.Z,{"aria-label":(0,h.I)({id:"theme.docs.breadcrumbs.home",message:"Home page",description:"The ARIA label for the home page in the breadcrumbs"}),className:"breadcrumbs__link",href:e,children:(0,i.jsx)(Et,{className:Ht.breadcrumbHomeIcon})})})}const It={breadcrumbsContainer:"breadcrumbsContainer_Z_bl"};function Mt(e){let{children:t,href:n,isLast:s}=e;const a="breadcrumbs__link";return s?(0,i.jsx)("span",{className:a,itemProp:"name",children:t}):n?(0,i.jsx)(p.Z,{className:a,href:n,itemProp:"item",children:(0,i.jsx)("span",{itemProp:"name",children:t})}):(0,i.jsx)("span",{className:a,children:t})}function St(e){let{children:t,active:n,index:s,addMicrodata:a}=e;return(0,i.jsxs)("li",{...a&&{itemScope:!0,itemProp:"itemListElement",itemType:"https://schema.org/ListItem"},className:(0,u.Z)("breadcrumbs__item",{"breadcrumbs__item--active":n}),children:[t,(0,i.jsx)("meta",{itemProp:"position",content:String(s+1)})]})}function Ut(){const e=(0,wt.s1)(),t=(0,Zt.Ns)();return e?(0,i.jsx)("nav",{className:(0,u.Z)(v.k.docs.docBreadcrumbs,It.breadcrumbsContainer),"aria-label":(0,h.I)({id:"theme.docs.breadcrumbs.navAriaLabel",message:"Breadcrumbs",description:"The ARIA label for the breadcrumbs"}),children:(0,i.jsxs)("ul",{className:"breadcrumbs",itemScope:!0,itemType:"https://schema.org/BreadcrumbList",children:[t&&(0,i.jsx)(At,{}),e.map(((t,n)=>{const s=n===e.length-1,a="category"===t.type&&t.linkUnlisted?void 0:t.href;return(0,i.jsx)(St,{active:s,index:n,addMicrodata:!!a,children:(0,i.jsx)(Mt,{href:a,isLast:s,children:t.label})},n)}))]})}):null}function zt(){return(0,i.jsx)(h.Z,{id:"theme.unlistedContent.title",description:"The unlisted content banner title",children:"Unlisted page"})}function Vt(){return(0,i.jsx)(h.Z,{id:"theme.unlistedContent.message",description:"The unlisted content banner message",children:"This page is unlisted. Search engines will not index it, and only users having a direct link can access it."})}function Rt(){return(0,i.jsx)(he.Z,{children:(0,i.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})}function Ot(e){let{className:t}=e;return(0,i.jsx)(Lt,{type:"caution",title:(0,i.jsx)(zt,{}),className:(0,u.Z)(t,v.k.common.unlistedBanner),children:(0,i.jsx)(Vt,{})})}function Pt(e){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(Rt,{}),(0,i.jsx)(Ot,{...e})]})}const $t={docItemContainer:"docItemContainer_Djhp",docItemCol:"docItemCol_VOVn"};function Dt(e){let{children:t}=e;const n=function(){const{frontMatter:e,toc:t}=r(),n=(0,m.i)(),s=e.hide_table_of_contents,a=!s&&t.length>0;return{hidden:s,mobile:a?(0,i.jsx)(oe,{}):void 0,desktop:!a||"desktop"!==n&&"ssr"!==n?void 0:(0,i.jsx)(de,{})}}(),{metadata:{unlisted:s}}=r();return(0,i.jsxs)("div",{className:"row",children:[(0,i.jsxs)("div",{className:(0,u.Z)("col",!n.hidden&&$t.docItemCol),children:[s&&(0,i.jsx)(Pt,{}),(0,i.jsx)(_,{}),(0,i.jsxs)("div",{className:$t.docItemContainer,children:[(0,i.jsxs)("article",{children:[(0,i.jsx)(Ut,{}),(0,i.jsx)(w,{}),n.mobile,(0,i.jsx)(_t,{children:t}),(0,i.jsx)(P,{})]}),(0,i.jsx)(b,{})]})]}),n.desktop&&(0,i.jsx)("div",{className:"col col--3",children:n.desktop})]})}function Wt(e){const t=`docs-doc-id-${e.content.metadata.id}`,n=e.content;return(0,i.jsx)(c,{content:e.content,children:(0,i.jsxs)(a.FG,{className:t,children:[(0,i.jsx)(d,{}),(0,i.jsx)(Dt,{children:(0,i.jsx)(n,{})})]})})}},7594:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,a,o]=t;if(s&&o){s=parseInt(s),o=parseInt(o);const e=s<o?1:-1;"-"!==a&&".."!==a&&"\u2025"!==a||(o+=e);for(let t=s;t!==o;t+=e)n.push(t)}}return n}t.default=n,e.exports=n},1151:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,a:()=>i});var s=n(7294);const a={},o=s.createContext(a);function i(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/1a4e3797.be02ef92.js b/docs/assets/js/1a4e3797.be02ef92.js deleted file mode 100644 index eebd9ae3ef..0000000000 --- a/docs/assets/js/1a4e3797.be02ef92.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see 1a4e3797.be02ef92.js.LICENSE.txt */ -(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7920],{7331:e=>{function t(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}function i(e){return void 0===e}e.exports=t,t.prototype._events=void 0,t.prototype._maxListeners=void 0,t.defaultMaxListeners=10,t.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},t.prototype.emit=function(e){var t,a,s,c,u,o;if(this._events||(this._events={}),"error"===e&&(!this._events.error||n(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var h=new Error('Uncaught, unspecified "error" event. ('+t+")");throw h.context=t,h}if(i(a=this._events[e]))return!1;if(r(a))switch(arguments.length){case 1:a.call(this);break;case 2:a.call(this,arguments[1]);break;case 3:a.call(this,arguments[1],arguments[2]);break;default:c=Array.prototype.slice.call(arguments,1),a.apply(this,c)}else if(n(a))for(c=Array.prototype.slice.call(arguments,1),s=(o=a.slice()).length,u=0;u<s;u++)o[u].apply(this,c);return!0},t.prototype.addListener=function(e,a){var s;if(!r(a))throw TypeError("listener must be a function");return this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,r(a.listener)?a.listener:a),this._events[e]?n(this._events[e])?this._events[e].push(a):this._events[e]=[this._events[e],a]:this._events[e]=a,n(this._events[e])&&!this._events[e].warned&&(s=i(this._maxListeners)?t.defaultMaxListeners:this._maxListeners)&&s>0&&this._events[e].length>s&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t){if(!r(t))throw TypeError("listener must be a function");var n=!1;function i(){this.removeListener(e,i),n||(n=!0,t.apply(this,arguments))}return i.listener=t,this.on(e,i),this},t.prototype.removeListener=function(e,t){var i,a,s,c;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(s=(i=this._events[e]).length,a=-1,i===t||r(i.listener)&&i.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(n(i)){for(c=s;c-- >0;)if(i[c]===t||i[c].listener&&i[c].listener===t){a=c;break}if(a<0)return this;1===i.length?(i.length=0,delete this._events[e]):i.splice(a,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},t.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r(n=this._events[e]))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},t.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},t.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},t.listenerCount=function(e,t){return e.listenerCount(t)}},8131:(e,t,r)=>{"use strict";var n=r(9374),i=r(7775),a=r(3076);function s(e,t,r){return new n(e,t,r)}s.version=r(4336),s.AlgoliaSearchHelper=n,s.SearchParameters=i,s.SearchResults=a,e.exports=s},8078:(e,t,r)=>{"use strict";var n=r(7331);function i(e,t){this.main=e,this.fn=t,this.lastResults=null}r(4853)(i,n),i.prototype.detach=function(){this.removeAllListeners(),this.main.detachDerivedHelper(this)},i.prototype.getModifiedState=function(e){return this.fn(e)},e.exports=i},2437:(e,t,r)=>{"use strict";var n=r(2344),i=r(9803),a=r(116),s={addRefinement:function(e,t,r){if(s.isRefined(e,t,r))return e;var i=""+r,a=e[t]?e[t].concat(i):[i],c={};return c[t]=a,n({},c,e)},removeRefinement:function(e,t,r){if(void 0===r)return s.clearRefinement(e,(function(e,r){return t===r}));var n=""+r;return s.clearRefinement(e,(function(e,r){return t===r&&n===e}))},toggleRefinement:function(e,t,r){if(void 0===r)throw new Error("toggleRefinement should be used with a value");return s.isRefined(e,t,r)?s.removeRefinement(e,t,r):s.addRefinement(e,t,r)},clearRefinement:function(e,t,r){if(void 0===t)return a(e)?{}:e;if("string"==typeof t)return i(e,[t]);if("function"==typeof t){var n=!1,s=Object.keys(e).reduce((function(i,a){var s=e[a]||[],c=s.filter((function(e){return!t(e,a,r)}));return c.length!==s.length&&(n=!0),i[a]=c,i}),{});return n?s:e}},isRefined:function(e,t,r){var n=!!e[t]&&e[t].length>0;if(void 0===r||!n)return n;var i=""+r;return-1!==e[t].indexOf(i)}};e.exports=s},7775:(e,t,r)=>{"use strict";var n=r(185),i=r(2344),a=r(2686),s=r(7888),c=r(8023),u=r(9803),o=r(116),h=r(6801),f=r(2437);function l(e,t){return Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((function(e,r){return l(t[r],e)})):e===t}function m(e){var t=e?m._parseNumbers(e):{};void 0===t.userToken||h(t.userToken)||console.warn("[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}"),this.facets=t.facets||[],this.disjunctiveFacets=t.disjunctiveFacets||[],this.hierarchicalFacets=t.hierarchicalFacets||[],this.facetsRefinements=t.facetsRefinements||{},this.facetsExcludes=t.facetsExcludes||{},this.disjunctiveFacetsRefinements=t.disjunctiveFacetsRefinements||{},this.numericRefinements=t.numericRefinements||{},this.tagRefinements=t.tagRefinements||[],this.hierarchicalFacetsRefinements=t.hierarchicalFacetsRefinements||{};var r=this;Object.keys(t).forEach((function(e){var n=-1!==m.PARAMETERS.indexOf(e),i=void 0!==t[e];!n&&i&&(r[e]=t[e])}))}m.PARAMETERS=Object.keys(new m),m._parseNumbers=function(e){if(e instanceof m)return e;var t={};if(["aroundPrecision","aroundRadius","getRankingInfo","minWordSizefor2Typos","minWordSizefor1Typo","page","maxValuesPerFacet","distinct","minimumAroundRadius","hitsPerPage","minProximity"].forEach((function(r){var n=e[r];if("string"==typeof n){var i=parseFloat(n);t[r]=isNaN(i)?n:i}})),Array.isArray(e.insideBoundingBox)&&(t.insideBoundingBox=e.insideBoundingBox.map((function(e){return Array.isArray(e)?e.map((function(e){return parseFloat(e)})):e}))),e.numericRefinements){var r={};Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t]||{};r[t]={},Object.keys(n).forEach((function(e){var i=n[e].map((function(e){return Array.isArray(e)?e.map((function(e){return"string"==typeof e?parseFloat(e):e})):"string"==typeof e?parseFloat(e):e}));r[t][e]=i}))})),t.numericRefinements=r}return n({},e,t)},m.make=function(e){var t=new m(e);return(e.hierarchicalFacets||[]).forEach((function(e){if(e.rootPath){var r=t.getHierarchicalRefinement(e.name);r.length>0&&0!==r[0].indexOf(e.rootPath)&&(t=t.clearRefinements(e.name)),0===(r=t.getHierarchicalRefinement(e.name)).length&&(t=t.toggleHierarchicalFacetRefinement(e.name,e.rootPath))}})),t},m.validate=function(e,t){var r=t||{};return e.tagFilters&&r.tagRefinements&&r.tagRefinements.length>0?new Error("[Tags] Cannot switch from the managed tag API to the advanced API. It is probably an error, if it is really what you want, you should first clear the tags with clearTags method."):e.tagRefinements.length>0&&r.tagFilters?new Error("[Tags] Cannot switch from the advanced tag API to the managed API. It is probably an error, if it is not, you should first clear the tags with clearTags method."):e.numericFilters&&r.numericRefinements&&o(r.numericRefinements)?new Error("[Numeric filters] Can't switch from the advanced to the managed API. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):o(e.numericRefinements)&&r.numericFilters?new Error("[Numeric filters] Can't switch from the managed API to the advanced. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):null},m.prototype={constructor:m,clearRefinements:function(e){var t={numericRefinements:this._clearNumericRefinements(e),facetsRefinements:f.clearRefinement(this.facetsRefinements,e,"conjunctiveFacet"),facetsExcludes:f.clearRefinement(this.facetsExcludes,e,"exclude"),disjunctiveFacetsRefinements:f.clearRefinement(this.disjunctiveFacetsRefinements,e,"disjunctiveFacet"),hierarchicalFacetsRefinements:f.clearRefinement(this.hierarchicalFacetsRefinements,e,"hierarchicalFacet")};return t.numericRefinements===this.numericRefinements&&t.facetsRefinements===this.facetsRefinements&&t.facetsExcludes===this.facetsExcludes&&t.disjunctiveFacetsRefinements===this.disjunctiveFacetsRefinements&&t.hierarchicalFacetsRefinements===this.hierarchicalFacetsRefinements?this:this.setQueryParameters(t)},clearTags:function(){return void 0===this.tagFilters&&0===this.tagRefinements.length?this:this.setQueryParameters({tagFilters:void 0,tagRefinements:[]})},setIndex:function(e){return e===this.index?this:this.setQueryParameters({index:e})},setQuery:function(e){return e===this.query?this:this.setQueryParameters({query:e})},setPage:function(e){return e===this.page?this:this.setQueryParameters({page:e})},setFacets:function(e){return this.setQueryParameters({facets:e})},setDisjunctiveFacets:function(e){return this.setQueryParameters({disjunctiveFacets:e})},setHitsPerPage:function(e){return this.hitsPerPage===e?this:this.setQueryParameters({hitsPerPage:e})},setTypoTolerance:function(e){return this.typoTolerance===e?this:this.setQueryParameters({typoTolerance:e})},addNumericRefinement:function(e,t,r){var i=c(r);if(this.isNumericRefined(e,t,i))return this;var a=n({},this.numericRefinements);return a[e]=n({},a[e]),a[e][t]?(a[e][t]=a[e][t].slice(),a[e][t].push(i)):a[e][t]=[i],this.setQueryParameters({numericRefinements:a})},getConjunctiveRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsRefinements[e]||[]},getDisjunctiveRefinements:function(e){return this.isDisjunctiveFacet(e)&&this.disjunctiveFacetsRefinements[e]||[]},getHierarchicalRefinement:function(e){return this.hierarchicalFacetsRefinements[e]||[]},getExcludeRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsExcludes[e]||[]},removeNumericRefinement:function(e,t,r){return void 0!==r?this.isNumericRefined(e,t,r)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(n,i){return i===e&&n.op===t&&l(n.val,c(r))}))}):this:void 0!==t?this.isNumericRefined(e,t)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(r,n){return n===e&&r.op===t}))}):this:this.isNumericRefined(e)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(t,r){return r===e}))}):this},getNumericRefinements:function(e){return this.numericRefinements[e]||{}},getNumericRefinement:function(e,t){return this.numericRefinements[e]&&this.numericRefinements[e][t]},_clearNumericRefinements:function(e){if(void 0===e)return o(this.numericRefinements)?{}:this.numericRefinements;if("string"==typeof e)return u(this.numericRefinements,[e]);if("function"==typeof e){var t=!1,r=this.numericRefinements,n=Object.keys(r).reduce((function(n,i){var a=r[i],s={};return a=a||{},Object.keys(a).forEach((function(r){var n=a[r]||[],c=[];n.forEach((function(t){e({val:t,op:r},i,"numeric")||c.push(t)})),c.length!==n.length&&(t=!0),s[r]=c})),n[i]=s,n}),{});return t?n:this.numericRefinements}},addFacet:function(e){return this.isConjunctiveFacet(e)?this:this.setQueryParameters({facets:this.facets.concat([e])})},addDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this:this.setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.concat([e])})},addHierarchicalFacet:function(e){if(this.isHierarchicalFacet(e.name))throw new Error("Cannot declare two hierarchical facets with the same name: `"+e.name+"`");return this.setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.concat([e])})},addFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsRefinements,e,t)?this:this.setQueryParameters({facetsRefinements:f.addRefinement(this.facetsRefinements,e,t)})},addExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsExcludes,e,t)?this:this.setQueryParameters({facetsExcludes:f.addRefinement(this.facetsExcludes,e,t)})},addDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return f.isRefined(this.disjunctiveFacetsRefinements,e,t)?this:this.setQueryParameters({disjunctiveFacetsRefinements:f.addRefinement(this.disjunctiveFacetsRefinements,e,t)})},addTagRefinement:function(e){if(this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.concat(e)};return this.setQueryParameters(t)},removeFacet:function(e){return this.isConjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({facets:this.facets.filter((function(t){return t!==e}))}):this},removeDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.filter((function(t){return t!==e}))}):this},removeHierarchicalFacet:function(e){return this.isHierarchicalFacet(e)?this.clearRefinements(e).setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.filter((function(t){return t.name!==e}))}):this},removeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsRefinements,e,t)?this.setQueryParameters({facetsRefinements:f.removeRefinement(this.facetsRefinements,e,t)}):this},removeExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsExcludes,e,t)?this.setQueryParameters({facetsExcludes:f.removeRefinement(this.facetsExcludes,e,t)}):this},removeDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return f.isRefined(this.disjunctiveFacetsRefinements,e,t)?this.setQueryParameters({disjunctiveFacetsRefinements:f.removeRefinement(this.disjunctiveFacetsRefinements,e,t)}):this},removeTagRefinement:function(e){if(!this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.filter((function(t){return t!==e}))};return this.setQueryParameters(t)},toggleRefinement:function(e,t){return this.toggleFacetRefinement(e,t)},toggleFacetRefinement:function(e,t){if(this.isHierarchicalFacet(e))return this.toggleHierarchicalFacetRefinement(e,t);if(this.isConjunctiveFacet(e))return this.toggleConjunctiveFacetRefinement(e,t);if(this.isDisjunctiveFacet(e))return this.toggleDisjunctiveFacetRefinement(e,t);throw new Error("Cannot refine the undeclared facet "+e+"; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets")},toggleConjunctiveFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsRefinements:f.toggleRefinement(this.facetsRefinements,e,t)})},toggleExcludeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsExcludes:f.toggleRefinement(this.facetsExcludes,e,t)})},toggleDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return this.setQueryParameters({disjunctiveFacetsRefinements:f.toggleRefinement(this.disjunctiveFacetsRefinements,e,t)})},toggleHierarchicalFacetRefinement:function(e,t){if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration");var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e)),n={};return void 0!==this.hierarchicalFacetsRefinements[e]&&this.hierarchicalFacetsRefinements[e].length>0&&(this.hierarchicalFacetsRefinements[e][0]===t||0===this.hierarchicalFacetsRefinements[e][0].indexOf(t+r))?-1===t.indexOf(r)?n[e]=[]:n[e]=[t.slice(0,t.lastIndexOf(r))]:n[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:i({},n,this.hierarchicalFacetsRefinements)})},addHierarchicalFacetRefinement:function(e,t){if(this.isHierarchicalFacetRefined(e))throw new Error(e+" is already refined.");if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration.");var r={};return r[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:i({},r,this.hierarchicalFacetsRefinements)})},removeHierarchicalFacetRefinement:function(e){if(!this.isHierarchicalFacetRefined(e))return this;var t={};return t[e]=[],this.setQueryParameters({hierarchicalFacetsRefinements:i({},t,this.hierarchicalFacetsRefinements)})},toggleTagRefinement:function(e){return this.isTagRefined(e)?this.removeTagRefinement(e):this.addTagRefinement(e)},isDisjunctiveFacet:function(e){return this.disjunctiveFacets.indexOf(e)>-1},isHierarchicalFacet:function(e){return void 0!==this.getHierarchicalFacetByName(e)},isConjunctiveFacet:function(e){return this.facets.indexOf(e)>-1},isFacetRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&f.isRefined(this.facetsRefinements,e,t)},isExcludeRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&f.isRefined(this.facetsExcludes,e,t)},isDisjunctiveFacetRefined:function(e,t){return!!this.isDisjunctiveFacet(e)&&f.isRefined(this.disjunctiveFacetsRefinements,e,t)},isHierarchicalFacetRefined:function(e,t){if(!this.isHierarchicalFacet(e))return!1;var r=this.getHierarchicalRefinement(e);return t?-1!==r.indexOf(t):r.length>0},isNumericRefined:function(e,t,r){if(void 0===r&&void 0===t)return!!this.numericRefinements[e];var n=this.numericRefinements[e]&&void 0!==this.numericRefinements[e][t];if(void 0===r||!n)return n;var i,a,u=c(r),o=void 0!==(i=this.numericRefinements[e][t],a=u,s(i,(function(e){return l(e,a)})));return n&&o},isTagRefined:function(e){return-1!==this.tagRefinements.indexOf(e)},getRefinedDisjunctiveFacets:function(){var e=this,t=a(Object.keys(this.numericRefinements).filter((function(t){return Object.keys(e.numericRefinements[t]).length>0})),this.disjunctiveFacets);return Object.keys(this.disjunctiveFacetsRefinements).filter((function(t){return e.disjunctiveFacetsRefinements[t].length>0})).concat(t).concat(this.getRefinedHierarchicalFacets())},getRefinedHierarchicalFacets:function(){var e=this;return a(this.hierarchicalFacets.map((function(e){return e.name})),Object.keys(this.hierarchicalFacetsRefinements).filter((function(t){return e.hierarchicalFacetsRefinements[t].length>0})))},getUnrefinedDisjunctiveFacets:function(){var e=this.getRefinedDisjunctiveFacets();return this.disjunctiveFacets.filter((function(t){return-1===e.indexOf(t)}))},managedParameters:["index","facets","disjunctiveFacets","facetsRefinements","hierarchicalFacets","facetsExcludes","disjunctiveFacetsRefinements","numericRefinements","tagRefinements","hierarchicalFacetsRefinements"],getQueryParams:function(){var e=this.managedParameters,t={},r=this;return Object.keys(this).forEach((function(n){var i=r[n];-1===e.indexOf(n)&&void 0!==i&&(t[n]=i)})),t},setQueryParameter:function(e,t){if(this[e]===t)return this;var r={};return r[e]=t,this.setQueryParameters(r)},setQueryParameters:function(e){if(!e)return this;var t=m.validate(this,e);if(t)throw t;var r=this,n=m._parseNumbers(e),i=Object.keys(this).reduce((function(e,t){return e[t]=r[t],e}),{}),a=Object.keys(n).reduce((function(e,t){var r=void 0!==e[t],i=void 0!==n[t];return r&&!i?u(e,[t]):(i&&(e[t]=n[t]),e)}),i);return new this.constructor(a)},resetPage:function(){return void 0===this.page?this:this.setPage(0)},_getHierarchicalFacetSortBy:function(e){return e.sortBy||["isRefined:desc","name:asc"]},_getHierarchicalFacetSeparator:function(e){return e.separator||" > "},_getHierarchicalRootPath:function(e){return e.rootPath||null},_getHierarchicalShowParentLevel:function(e){return"boolean"!=typeof e.showParentLevel||e.showParentLevel},getHierarchicalFacetByName:function(e){return s(this.hierarchicalFacets,(function(t){return t.name===e}))},getHierarchicalFacetBreadcrumb:function(e){if(!this.isHierarchicalFacet(e))return[];var t=this.getHierarchicalRefinement(e)[0];if(!t)return[];var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e));return t.split(r).map((function(e){return e.trim()}))},toString:function(){return JSON.stringify(this,null,2)}},e.exports=m},210:(e,t,r)=>{"use strict";e.exports=function(e){return function(t,r){var s=e.hierarchicalFacets[r],o=e.hierarchicalFacetsRefinements[s.name]&&e.hierarchicalFacetsRefinements[s.name][0]||"",h=e._getHierarchicalFacetSeparator(s),f=e._getHierarchicalRootPath(s),l=e._getHierarchicalShowParentLevel(s),m=a(e._getHierarchicalFacetSortBy(s)),d=t.every((function(e){return e.exhaustive})),p=function(e,t,r,a,s){return function(o,h,f){var l=o;if(f>0){var m=0;for(l=o;m<f;){var d=l&&Array.isArray(l.data)?l.data:[];l=i(d,(function(e){return e.isRefined})),m++}}if(l){var p=Object.keys(h.data).map((function(e){return[e,h.data[e]]})).filter((function(e){return function(e,t,r,n,i,a){if(i&&(0!==e.indexOf(i)||i===e))return!1;return!i&&-1===e.indexOf(n)||i&&e.split(n).length-i.split(n).length==1||-1===e.indexOf(n)&&-1===r.indexOf(n)||0===r.indexOf(e)||0===e.indexOf(t+n)&&(a||0===e.indexOf(r))}(e[0],l.path||r,s,t,r,a)}));l.data=n(p.map((function(e){var r=e[0];return function(e,t,r,n,i){var a=t.split(r);return{name:a[a.length-1].trim(),path:t,escapedValue:c(t),count:e,isRefined:n===t||0===n.indexOf(t+r),exhaustive:i,data:null}}(e[1],r,t,u(s),h.exhaustive)})),e[0],e[1])}return o}}(m,h,f,l,o),v=t;return f&&(v=t.slice(f.split(h).length)),v.reduce(p,{name:e.hierarchicalFacets[r].name,count:null,isRefined:!0,path:null,escapedValue:null,exhaustive:d,data:null})}};var n=r(2148),i=r(7888),a=r(2293),s=r(4039),c=s.escapeFacetValue,u=s.unescapeFacetValue},3076:(e,t,r)=>{"use strict";var n=r(185),i=r(2344),a=r(2148),s=r(4587),c=r(7888),u=r(9725),o=r(2293),h=r(4039),f=h.escapeFacetValue,l=h.unescapeFacetValue,m=r(210);function d(e){var t={};return e.forEach((function(e,r){t[e]=r})),t}function p(e,t,r){t&&t[r]&&(e.stats=t[r])}function v(e,t,r){var a=t[0];this._rawResults=t;var o=this;Object.keys(a).forEach((function(e){o[e]=a[e]})),Object.keys(r||{}).forEach((function(e){o[e]=r[e]})),this.processingTimeMS=t.reduce((function(e,t){return void 0===t.processingTimeMS?e:e+t.processingTimeMS}),0),this.disjunctiveFacets=[],this.hierarchicalFacets=e.hierarchicalFacets.map((function(){return[]})),this.facets=[];var h=e.getRefinedDisjunctiveFacets(),f=d(e.facets),v=d(e.disjunctiveFacets),g=1,y=a.facets||{};Object.keys(y).forEach((function(t){var r,n,i=y[t],s=(r=e.hierarchicalFacets,n=t,c(r,(function(e){return(e.attributes||[]).indexOf(n)>-1})));if(s){var h=s.attributes.indexOf(t),l=u(e.hierarchicalFacets,(function(e){return e.name===s.name}));o.hierarchicalFacets[l][h]={attribute:t,data:i,exhaustive:a.exhaustiveFacetsCount}}else{var m,d=-1!==e.disjunctiveFacets.indexOf(t),g=-1!==e.facets.indexOf(t);d&&(m=v[t],o.disjunctiveFacets[m]={name:t,data:i,exhaustive:a.exhaustiveFacetsCount},p(o.disjunctiveFacets[m],a.facets_stats,t)),g&&(m=f[t],o.facets[m]={name:t,data:i,exhaustive:a.exhaustiveFacetsCount},p(o.facets[m],a.facets_stats,t))}})),this.hierarchicalFacets=s(this.hierarchicalFacets),h.forEach((function(r){var s=t[g],c=s&&s.facets?s.facets:{},h=e.getHierarchicalFacetByName(r);Object.keys(c).forEach((function(t){var r,f=c[t];if(h){r=u(e.hierarchicalFacets,(function(e){return e.name===h.name}));var m=u(o.hierarchicalFacets[r],(function(e){return e.attribute===t}));if(-1===m)return;o.hierarchicalFacets[r][m].data=n({},o.hierarchicalFacets[r][m].data,f)}else{r=v[t];var d=a.facets&&a.facets[t]||{};o.disjunctiveFacets[r]={name:t,data:i({},f,d),exhaustive:s.exhaustiveFacetsCount},p(o.disjunctiveFacets[r],s.facets_stats,t),e.disjunctiveFacetsRefinements[t]&&e.disjunctiveFacetsRefinements[t].forEach((function(n){!o.disjunctiveFacets[r].data[n]&&e.disjunctiveFacetsRefinements[t].indexOf(l(n))>-1&&(o.disjunctiveFacets[r].data[n]=0)}))}})),g++})),e.getRefinedHierarchicalFacets().forEach((function(r){var n=e.getHierarchicalFacetByName(r),a=e._getHierarchicalFacetSeparator(n),s=e.getHierarchicalRefinement(r);0===s.length||s[0].split(a).length<2||t.slice(g).forEach((function(t){var r=t&&t.facets?t.facets:{};Object.keys(r).forEach((function(t){var c=r[t],h=u(e.hierarchicalFacets,(function(e){return e.name===n.name})),f=u(o.hierarchicalFacets[h],(function(e){return e.attribute===t}));if(-1!==f){var l={};if(s.length>0){var m=s[0].split(a)[0];l[m]=o.hierarchicalFacets[h][f].data[m]}o.hierarchicalFacets[h][f].data=i(l,c,o.hierarchicalFacets[h][f].data)}})),g++}))})),Object.keys(e.facetsExcludes).forEach((function(t){var r=e.facetsExcludes[t],n=f[t];o.facets[n]={name:t,data:a.facets[t],exhaustive:a.exhaustiveFacetsCount},r.forEach((function(e){o.facets[n]=o.facets[n]||{name:t},o.facets[n].data=o.facets[n].data||{},o.facets[n].data[e]=0}))})),this.hierarchicalFacets=this.hierarchicalFacets.map(m(e)),this.facets=s(this.facets),this.disjunctiveFacets=s(this.disjunctiveFacets),this._state=e}function g(e,t,r,n){if(n=n||0,Array.isArray(t))return e(t,r[n]);if(!t.data||0===t.data.length)return t;var a=t.data.map((function(t){return g(e,t,r,n+1)})),s=e(a,r[n]);return i({data:s},t)}function y(e,t){var r=c(e,(function(e){return e.name===t}));return r&&r.stats}function R(e,t,r,n,i){var a=c(i,(function(e){return e.name===r})),s=a&&a.data&&a.data[n]?a.data[n]:0,u=a&&a.exhaustive||!1;return{type:t,attributeName:r,name:n,count:s,exhaustive:u}}v.prototype.getFacetByName=function(e){function t(t){return t.name===e}return c(this.facets,t)||c(this.disjunctiveFacets,t)||c(this.hierarchicalFacets,t)},v.DEFAULT_SORT=["isRefined:desc","count:desc","name:asc"],v.prototype.getFacetValues=function(e,t){var r=function(e,t){function r(e){return e.name===t}if(e._state.isConjunctiveFacet(t)){var n=c(e.facets,r);return n?Object.keys(n.data).map((function(r){var i=f(r);return{name:r,escapedValue:i,count:n.data[r],isRefined:e._state.isFacetRefined(t,i),isExcluded:e._state.isExcludeRefined(t,r)}})):[]}if(e._state.isDisjunctiveFacet(t)){var i=c(e.disjunctiveFacets,r);return i?Object.keys(i.data).map((function(r){var n=f(r);return{name:r,escapedValue:n,count:i.data[r],isRefined:e._state.isDisjunctiveFacetRefined(t,n)}})):[]}if(e._state.isHierarchicalFacet(t))return c(e.hierarchicalFacets,r)}(this,e);if(r){var n,s=i({},t,{sortBy:v.DEFAULT_SORT,facetOrdering:!(t&&t.sortBy)}),u=this;if(Array.isArray(r))n=[e];else n=u._state.getHierarchicalFacetByName(r.name).attributes;return g((function(e,t){if(s.facetOrdering){var r=function(e,t){return e.renderingContent&&e.renderingContent.facetOrdering&&e.renderingContent.facetOrdering.values&&e.renderingContent.facetOrdering.values[t]}(u,t);if(Boolean(r))return function(e,t){var r=[],n=[],i=(t.order||[]).reduce((function(e,t,r){return e[t]=r,e}),{});e.forEach((function(e){var t=e.path||e.name;void 0!==i[t]?r[i[t]]=e:n.push(e)})),r=r.filter((function(e){return e}));var s,c=t.sortRemainingBy;return"hidden"===c?r:(s="alpha"===c?[["path","name"],["asc","asc"]]:[["count"],["desc"]],r.concat(a(n,s[0],s[1])))}(e,r)}if(Array.isArray(s.sortBy)){var n=o(s.sortBy,v.DEFAULT_SORT);return a(e,n[0],n[1])}if("function"==typeof s.sortBy)return function(e,t){return t.sort(e)}(s.sortBy,e);throw new Error("options.sortBy is optional but if defined it must be either an array of string (predicates) or a sorting function")}),r,n)}},v.prototype.getFacetStats=function(e){return this._state.isConjunctiveFacet(e)?y(this.facets,e):this._state.isDisjunctiveFacet(e)?y(this.disjunctiveFacets,e):void 0},v.prototype.getRefinements=function(){var e=this._state,t=this,r=[];return Object.keys(e.facetsRefinements).forEach((function(n){e.facetsRefinements[n].forEach((function(i){r.push(R(e,"facet",n,i,t.facets))}))})),Object.keys(e.facetsExcludes).forEach((function(n){e.facetsExcludes[n].forEach((function(i){r.push(R(e,"exclude",n,i,t.facets))}))})),Object.keys(e.disjunctiveFacetsRefinements).forEach((function(n){e.disjunctiveFacetsRefinements[n].forEach((function(i){r.push(R(e,"disjunctive",n,i,t.disjunctiveFacets))}))})),Object.keys(e.hierarchicalFacetsRefinements).forEach((function(n){e.hierarchicalFacetsRefinements[n].forEach((function(i){r.push(function(e,t,r,n){var i=e.getHierarchicalFacetByName(t),a=e._getHierarchicalFacetSeparator(i),s=r.split(a),u=c(n,(function(e){return e.name===t})),o=s.reduce((function(e,t){var r=e&&c(e.data,(function(e){return e.name===t}));return void 0!==r?r:e}),u),h=o&&o.count||0,f=o&&o.exhaustive||!1,l=o&&o.path||"";return{type:"hierarchical",attributeName:t,name:l,count:h,exhaustive:f}}(e,n,i,t.hierarchicalFacets))}))})),Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t];Object.keys(n).forEach((function(e){n[e].forEach((function(n){r.push({type:"numeric",attributeName:t,name:n,numericValue:n,operator:e})}))}))})),e.tagRefinements.forEach((function(e){r.push({type:"tag",attributeName:"_tags",name:e})})),r},e.exports=v},9374:(e,t,r)=>{"use strict";var n=r(7775),i=r(3076),a=r(8078),s=r(6394),c=r(7331),u=r(4853),o=r(116),h=r(9803),f=r(185),l=r(4336),m=r(4039).escapeFacetValue;function d(e,t,r){"function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+l+")"),this.setClient(e);var i=r||{};i.index=t,this.state=n.make(i),this.lastResults=null,this._queryId=0,this._lastQueryIdReceived=-1,this.derivedHelpers=[],this._currentNbQueries=0}function p(e){if(e<0)throw new Error("Page requested below 0.");return this._change({state:this.state.setPage(e),isPageReset:!1}),this}function v(){return this.state.page}u(d,c),d.prototype.search=function(){return this._search({onlyWithDerivedHelpers:!1}),this},d.prototype.searchOnlyWithDerivedHelpers=function(){return this._search({onlyWithDerivedHelpers:!0}),this},d.prototype.getQuery=function(){var e=this.state;return s._getHitsSearchParams(e)},d.prototype.searchOnce=function(e,t){var r=e?this.state.setQueryParameters(e):this.state,n=s._getQueries(r.index,r),a=this;if(this._currentNbQueries++,this.emit("searchOnce",{state:r}),!t)return this.client.search(n).then((function(e){return a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),{content:new i(r,e.results),state:r,_originalResponse:e}}),(function(e){throw a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),e}));this.client.search(n).then((function(e){a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),t(null,new i(r,e.results),r)})).catch((function(e){a._currentNbQueries--,0===a._currentNbQueries&&a.emit("searchQueueEmpty"),t(e,null,r)}))},d.prototype.findAnswers=function(e){var t=this.state,r=this.derivedHelpers[0];if(!r)return Promise.resolve([]);var n=r.getModifiedState(t),i=f({attributesForPrediction:e.attributesForPrediction,nbHits:e.nbHits},{params:h(s._getHitsSearchParams(n),["attributesToSnippet","hitsPerPage","restrictSearchableAttributes","snippetEllipsisText"])}),a="search for answers was called, but this client does not have a function client.initIndex(index).findAnswers";if("function"!=typeof this.client.initIndex)throw new Error(a);var c=this.client.initIndex(n.index);if("function"!=typeof c.findAnswers)throw new Error(a);return c.findAnswers(n.query,e.queryLanguages,i)},d.prototype.searchForFacetValues=function(e,t,r,n){var i="function"==typeof this.client.searchForFacetValues,a="function"==typeof this.client.initIndex;if(!i&&!a&&"function"!=typeof this.client.search)throw new Error("search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues or client.initIndex(index).searchForFacetValues");var c=this.state.setQueryParameters(n||{}),u=c.isDisjunctiveFacet(e),o=s.getSearchForFacetQuery(e,t,r,c);this._currentNbQueries++;var h,f=this;return i?h=this.client.searchForFacetValues([{indexName:c.index,params:o}]):a?h=this.client.initIndex(c.index).searchForFacetValues(o):(delete o.facetName,h=this.client.search([{type:"facet",facet:e,indexName:c.index,params:o}]).then((function(e){return e.results[0]}))),this.emit("searchForFacetValues",{state:c,facet:e,query:t}),h.then((function(t){return f._currentNbQueries--,0===f._currentNbQueries&&f.emit("searchQueueEmpty"),(t=Array.isArray(t)?t[0]:t).facetHits.forEach((function(t){t.escapedValue=m(t.value),t.isRefined=u?c.isDisjunctiveFacetRefined(e,t.escapedValue):c.isFacetRefined(e,t.escapedValue)})),t}),(function(e){throw f._currentNbQueries--,0===f._currentNbQueries&&f.emit("searchQueueEmpty"),e}))},d.prototype.setQuery=function(e){return this._change({state:this.state.resetPage().setQuery(e),isPageReset:!0}),this},d.prototype.clearRefinements=function(e){return this._change({state:this.state.resetPage().clearRefinements(e),isPageReset:!0}),this},d.prototype.clearTags=function(){return this._change({state:this.state.resetPage().clearTags(),isPageReset:!0}),this},d.prototype.addDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addDisjunctiveRefine=function(){return this.addDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.addHierarchicalFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addHierarchicalFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().addNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.addFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addRefine=function(){return this.addFacetRefinement.apply(this,arguments)},d.prototype.addFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().addExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.addExclude=function(){return this.addFacetExclusion.apply(this,arguments)},d.prototype.addTag=function(e){return this._change({state:this.state.resetPage().addTagRefinement(e),isPageReset:!0}),this},d.prototype.removeNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().removeNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.removeDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeDisjunctiveRefine=function(){return this.removeDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.removeHierarchicalFacetRefinement=function(e){return this._change({state:this.state.resetPage().removeHierarchicalFacetRefinement(e),isPageReset:!0}),this},d.prototype.removeFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeRefine=function(){return this.removeFacetRefinement.apply(this,arguments)},d.prototype.removeFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().removeExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.removeExclude=function(){return this.removeFacetExclusion.apply(this,arguments)},d.prototype.removeTag=function(e){return this._change({state:this.state.resetPage().removeTagRefinement(e),isPageReset:!0}),this},d.prototype.toggleFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().toggleExcludeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleExclude=function(){return this.toggleFacetExclusion.apply(this,arguments)},d.prototype.toggleRefinement=function(e,t){return this.toggleFacetRefinement(e,t)},d.prototype.toggleFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().toggleFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleRefine=function(){return this.toggleFacetRefinement.apply(this,arguments)},d.prototype.toggleTag=function(e){return this._change({state:this.state.resetPage().toggleTagRefinement(e),isPageReset:!0}),this},d.prototype.nextPage=function(){var e=this.state.page||0;return this.setPage(e+1)},d.prototype.previousPage=function(){var e=this.state.page||0;return this.setPage(e-1)},d.prototype.setCurrentPage=p,d.prototype.setPage=p,d.prototype.setIndex=function(e){return this._change({state:this.state.resetPage().setIndex(e),isPageReset:!0}),this},d.prototype.setQueryParameter=function(e,t){return this._change({state:this.state.resetPage().setQueryParameter(e,t),isPageReset:!0}),this},d.prototype.setState=function(e){return this._change({state:n.make(e),isPageReset:!1}),this},d.prototype.overrideStateWithoutTriggeringChangeEvent=function(e){return this.state=new n(e),this},d.prototype.hasRefinements=function(e){return!!o(this.state.getNumericRefinements(e))||(this.state.isConjunctiveFacet(e)?this.state.isFacetRefined(e):this.state.isDisjunctiveFacet(e)?this.state.isDisjunctiveFacetRefined(e):!!this.state.isHierarchicalFacet(e)&&this.state.isHierarchicalFacetRefined(e))},d.prototype.isExcluded=function(e,t){return this.state.isExcludeRefined(e,t)},d.prototype.isDisjunctiveRefined=function(e,t){return this.state.isDisjunctiveFacetRefined(e,t)},d.prototype.hasTag=function(e){return this.state.isTagRefined(e)},d.prototype.isTagRefined=function(){return this.hasTagRefinements.apply(this,arguments)},d.prototype.getIndex=function(){return this.state.index},d.prototype.getCurrentPage=v,d.prototype.getPage=v,d.prototype.getTags=function(){return this.state.tagRefinements},d.prototype.getRefinements=function(e){var t=[];if(this.state.isConjunctiveFacet(e))this.state.getConjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"conjunctive"})})),this.state.getExcludeRefinements(e).forEach((function(e){t.push({value:e,type:"exclude"})}));else if(this.state.isDisjunctiveFacet(e)){this.state.getDisjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"disjunctive"})}))}var r=this.state.getNumericRefinements(e);return Object.keys(r).forEach((function(e){var n=r[e];t.push({value:n,operator:e,type:"numeric"})})),t},d.prototype.getNumericRefinement=function(e,t){return this.state.getNumericRefinement(e,t)},d.prototype.getHierarchicalFacetBreadcrumb=function(e){return this.state.getHierarchicalFacetBreadcrumb(e)},d.prototype._search=function(e){var t=this.state,r=[],n=[];e.onlyWithDerivedHelpers||(n=s._getQueries(t.index,t),r.push({state:t,queriesCount:n.length,helper:this}),this.emit("search",{state:t,results:this.lastResults}));var i=this.derivedHelpers.map((function(e){var n=e.getModifiedState(t),i=s._getQueries(n.index,n);return r.push({state:n,queriesCount:i.length,helper:e}),e.emit("search",{state:n,results:e.lastResults}),i})),a=Array.prototype.concat.apply(n,i),c=this._queryId++;this._currentNbQueries++;try{this.client.search(a).then(this._dispatchAlgoliaResponse.bind(this,r,c)).catch(this._dispatchAlgoliaError.bind(this,c))}catch(u){this.emit("error",{error:u})}},d.prototype._dispatchAlgoliaResponse=function(e,t,r){if(!(t<this._lastQueryIdReceived)){this._currentNbQueries-=t-this._lastQueryIdReceived,this._lastQueryIdReceived=t,0===this._currentNbQueries&&this.emit("searchQueueEmpty");var n=r.results.slice();e.forEach((function(e){var t=e.state,r=e.queriesCount,a=e.helper,s=n.splice(0,r),c=a.lastResults=new i(t,s);a.emit("result",{results:c,state:t})}))}},d.prototype._dispatchAlgoliaError=function(e,t){e<this._lastQueryIdReceived||(this._currentNbQueries-=e-this._lastQueryIdReceived,this._lastQueryIdReceived=e,this.emit("error",{error:t}),0===this._currentNbQueries&&this.emit("searchQueueEmpty"))},d.prototype.containsRefinement=function(e,t,r,n){return e||0!==t.length||0!==r.length||0!==n.length},d.prototype._hasDisjunctiveRefinements=function(e){return this.state.disjunctiveRefinements[e]&&this.state.disjunctiveRefinements[e].length>0},d.prototype._change=function(e){var t=e.state,r=e.isPageReset;t!==this.state&&(this.state=t,this.emit("change",{state:this.state,results:this.lastResults,isPageReset:r}))},d.prototype.clearCache=function(){return this.client.clearCache&&this.client.clearCache(),this},d.prototype.setClient=function(e){return this.client===e||("function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+l+")"),this.client=e),this},d.prototype.getClient=function(){return this.client},d.prototype.derive=function(e){var t=new a(this,e);return this.derivedHelpers.push(t),t},d.prototype.detachDerivedHelper=function(e){var t=this.derivedHelpers.indexOf(e);if(-1===t)throw new Error("Derived helper already detached");this.derivedHelpers.splice(t,1)},d.prototype.hasPendingRequests=function(){return this._currentNbQueries>0},e.exports=d},4587:e=>{"use strict";e.exports=function(e){return Array.isArray(e)?e.filter(Boolean):[]}},2344:e=>{"use strict";e.exports=function(){var e=Array.prototype.slice.call(arguments);return e.reduceRight((function(e,t){return Object.keys(Object(t)).forEach((function(r){void 0!==t[r]&&(void 0!==e[r]&&delete e[r],e[r]=t[r])})),e}),{})}},4039:e=>{"use strict";e.exports={escapeFacetValue:function(e){return"string"!=typeof e?e:String(e).replace(/^-/,"\\-")},unescapeFacetValue:function(e){return"string"!=typeof e?e:e.replace(/^\\-/,"-")}}},7888:e=>{"use strict";e.exports=function(e,t){if(Array.isArray(e))for(var r=0;r<e.length;r++)if(t(e[r]))return e[r]}},9725:e=>{"use strict";e.exports=function(e,t){if(!Array.isArray(e))return-1;for(var r=0;r<e.length;r++)if(t(e[r]))return r;return-1}},2293:(e,t,r)=>{"use strict";var n=r(7888);e.exports=function(e,t){var r=(t||[]).map((function(e){return e.split(":")}));return e.reduce((function(e,t){var i=t.split(":"),a=n(r,(function(e){return e[0]===i[0]}));return i.length>1||!a?(e[0].push(i[0]),e[1].push(i[1]),e):(e[0].push(a[0]),e[1].push(a[1]),e)}),[[],[]])}},4853:e=>{"use strict";e.exports=function(e,t){e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}},2686:e=>{"use strict";e.exports=function(e,t){return e.filter((function(r,n){return t.indexOf(r)>-1&&e.indexOf(r)===n}))}},185:e=>{"use strict";function t(e){return"function"==typeof e||Array.isArray(e)||"[object Object]"===Object.prototype.toString.call(e)}function r(e,n){if(e===n)return e;for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)&&"__proto__"!==i){var a=n[i],s=e[i];void 0!==s&&void 0===a||(t(s)&&t(a)?e[i]=r(s,a):e[i]="object"==typeof(c=a)&&null!==c?r(Array.isArray(c)?[]:{},c):c)}var c;return e}e.exports=function(e){t(e)||(e={});for(var n=1,i=arguments.length;n<i;n++){var a=arguments[n];t(a)&&r(e,a)}return e}},116:e=>{"use strict";e.exports=function(e){return e&&Object.keys(e).length>0}},9803:e=>{"use strict";e.exports=function(e,t){if(null===e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}},2148:e=>{"use strict";function t(e,t){if(e!==t){var r=void 0!==e,n=null===e,i=void 0!==t,a=null===t;if(!a&&e>t||n&&i||!r)return 1;if(!n&&e<t||a&&r||!i)return-1}return 0}e.exports=function(e,r,n){if(!Array.isArray(e))return[];Array.isArray(n)||(n=[]);var i=e.map((function(e,t){return{criteria:r.map((function(t){return e[t]})),index:t,value:e}}));return i.sort((function(e,r){for(var i=-1;++i<e.criteria.length;){var a=t(e.criteria[i],r.criteria[i]);if(a)return i>=n.length?a:"desc"===n[i]?-a:a}return e.index-r.index})),i.map((function(e){return e.value}))}},8023:e=>{"use strict";e.exports=function e(t){if("number"==typeof t)return t;if("string"==typeof t)return parseFloat(t);if(Array.isArray(t))return t.map(e);throw new Error("The value should be a number, a parsable string or an array of those.")}},6394:(e,t,r)=>{"use strict";var n=r(185);function i(e){return Object.keys(e).sort((function(e,t){return e.localeCompare(t)})).reduce((function(t,r){return t[r]=e[r],t}),{})}var a={_getQueries:function(e,t){var r=[];return r.push({indexName:e,params:a._getHitsSearchParams(t)}),t.getRefinedDisjunctiveFacets().forEach((function(n){r.push({indexName:e,params:a._getDisjunctiveFacetSearchParams(t,n)})})),t.getRefinedHierarchicalFacets().forEach((function(n){var i=t.getHierarchicalFacetByName(n),s=t.getHierarchicalRefinement(n),c=t._getHierarchicalFacetSeparator(i);if(s.length>0&&s[0].split(c).length>1){var u=s[0].split(c).slice(0,-1).reduce((function(e,t,r){return e.concat({attribute:i.attributes[r],value:0===r?t:[e[e.length-1].value,t].join(c)})}),[]);u.forEach((function(n,i){var s=a._getDisjunctiveFacetSearchParams(t,n.attribute,0===i),c=u[i-1];s.facetFilters=i>0?[c.attribute+":"+c.value]:void 0,r.push({indexName:e,params:s})}))}})),r},_getHitsSearchParams:function(e){var t=e.facets.concat(e.disjunctiveFacets).concat(a._getHitsHierarchicalFacetsAttributes(e)),r=a._getFacetFilters(e),s=a._getNumericFilters(e),c=a._getTagFilters(e),u={facets:t.indexOf("*")>-1?["*"]:t,tagFilters:c};return r.length>0&&(u.facetFilters=r),s.length>0&&(u.numericFilters=s),i(n({},e.getQueryParams(),u))},_getDisjunctiveFacetSearchParams:function(e,t,r){var s=a._getFacetFilters(e,t,r),c=a._getNumericFilters(e,t),u=a._getTagFilters(e),o={hitsPerPage:0,page:0,analytics:!1,clickAnalytics:!1};u.length>0&&(o.tagFilters=u);var h=e.getHierarchicalFacetByName(t);return o.facets=h?a._getDisjunctiveHierarchicalFacetAttribute(e,h,r):t,c.length>0&&(o.numericFilters=c),s.length>0&&(o.facetFilters=s),i(n({},e.getQueryParams(),o))},_getNumericFilters:function(e,t){if(e.numericFilters)return e.numericFilters;var r=[];return Object.keys(e.numericRefinements).forEach((function(n){var i=e.numericRefinements[n]||{};Object.keys(i).forEach((function(e){var a=i[e]||[];t!==n&&a.forEach((function(t){if(Array.isArray(t)){var i=t.map((function(t){return n+e+t}));r.push(i)}else r.push(n+e+t)}))}))})),r},_getTagFilters:function(e){return e.tagFilters?e.tagFilters:e.tagRefinements.join(",")},_getFacetFilters:function(e,t,r){var n=[],i=e.facetsRefinements||{};Object.keys(i).forEach((function(e){(i[e]||[]).forEach((function(t){n.push(e+":"+t)}))}));var a=e.facetsExcludes||{};Object.keys(a).forEach((function(e){(a[e]||[]).forEach((function(t){n.push(e+":-"+t)}))}));var s=e.disjunctiveFacetsRefinements||{};Object.keys(s).forEach((function(e){var r=s[e]||[];if(e!==t&&r&&0!==r.length){var i=[];r.forEach((function(t){i.push(e+":"+t)})),n.push(i)}}));var c=e.hierarchicalFacetsRefinements||{};return Object.keys(c).forEach((function(i){var a=(c[i]||[])[0];if(void 0!==a){var s,u,o=e.getHierarchicalFacetByName(i),h=e._getHierarchicalFacetSeparator(o),f=e._getHierarchicalRootPath(o);if(t===i){if(-1===a.indexOf(h)||!f&&!0===r||f&&f.split(h).length===a.split(h).length)return;f?(u=f.split(h).length-1,a=f):(u=a.split(h).length-2,a=a.slice(0,a.lastIndexOf(h))),s=o.attributes[u]}else u=a.split(h).length-1,s=o.attributes[u];s&&n.push([s+":"+a])}})),n},_getHitsHierarchicalFacetsAttributes:function(e){return e.hierarchicalFacets.reduce((function(t,r){var n=e.getHierarchicalRefinement(r.name)[0];if(!n)return t.push(r.attributes[0]),t;var i=e._getHierarchicalFacetSeparator(r),a=n.split(i).length,s=r.attributes.slice(0,a+1);return t.concat(s)}),[])},_getDisjunctiveHierarchicalFacetAttribute:function(e,t,r){var n=e._getHierarchicalFacetSeparator(t);if(!0===r){var i=e._getHierarchicalRootPath(t),a=0;return i&&(a=i.split(n).length),[t.attributes[a]]}var s=(e.getHierarchicalRefinement(t.name)[0]||"").split(n).length-1;return t.attributes.slice(0,s+1)},getSearchForFacetQuery:function(e,t,r,s){var c=s.isDisjunctiveFacet(e)?s.clearRefinements(e):s,u={facetQuery:t,facetName:e};return"number"==typeof r&&(u.maxFacetHits=r),i(n({},a._getHitsSearchParams(c),u))}};e.exports=a},6801:e=>{"use strict";e.exports=function(e){return null!==e&&/^[a-zA-Z0-9_-]{1,64}$/.test(e)}},4336:e=>{"use strict";e.exports="3.11.0"},290:function(e){e.exports=function(){"use strict";function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function r(r){for(var n=1;n<arguments.length;n++){var i=null!=arguments[n]?arguments[n]:{};n%2?t(Object(i),!0).forEach((function(t){e(r,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(i)):t(Object(i)).forEach((function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(i,e))}))}return r}function n(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],n=!0,i=!1,a=void 0;try{for(var s,c=e[Symbol.iterator]();!(n=(s=c.next()).done)&&(r.push(s.value),!t||r.length!==t);n=!0);}catch(e){i=!0,a=e}finally{try{n||null==c.return||c.return()}finally{if(i)throw a}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function a(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t<e.length;t++)r[t]=e[t];return r}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function s(e){var t,r="algoliasearch-client-js-".concat(e.key),n=function(){return void 0===t&&(t=e.localStorage||window.localStorage),t},a=function(){return JSON.parse(n().getItem(r)||"{}")};return{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){var r=JSON.stringify(e),n=a()[r];return Promise.all([n||t(),void 0!==n])})).then((function(e){var t=i(e,2),n=t[0],a=t[1];return Promise.all([n,a||r.miss(n)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var i=a();return i[JSON.stringify(e)]=t,n().setItem(r,JSON.stringify(i)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=a();delete t[JSON.stringify(e)],n().setItem(r,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){n().removeItem(r)}))}}}function c(e){var t=a(e.caches),r=t.shift();return void 0===r?{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return t().then((function(e){return Promise.all([e,r.miss(e)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return r.get(e,n,i).catch((function(){return c({caches:t}).get(e,n,i)}))},set:function(e,n){return r.set(e,n).catch((function(){return c({caches:t}).set(e,n)}))},delete:function(e){return r.delete(e).catch((function(){return c({caches:t}).delete(e)}))},clear:function(){return r.clear().catch((function(){return c({caches:t}).clear()}))}}}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(r,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);var s=n(),c=i&&i.miss||function(){return Promise.resolve()};return s.then((function(e){return c(e)})).then((function(){return s}))},set:function(r,n){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function o(e){for(var t=e.length-1;t>0;t--){var r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function h(e,t){return t?(Object.keys(t).forEach((function(r){e[r]=t[r](e)})),e):e}function f(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];var i=0;return e.replace(/%s/g,(function(){return encodeURIComponent(r[i++])}))}var l={WithinQueryParameters:0,WithinHeaders:1};function m(e,t){var r=e||{},n=r.data||{};return Object.keys(r).forEach((function(e){-1===["timeout","headers","queryParameters","data","cacheable"].indexOf(e)&&(n[e]=r[e])})),{data:Object.entries(n).length>0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var d={Read:1,Write:2,Any:3},p=1,v=2,g=3;function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:p;return r(r({},e),{},{status:t,lastUpdate:Date.now()})}function R(e){return"string"==typeof e?{protocol:"https",url:e,accept:d.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||d.Any}}var F="GET",b="POST";function P(e,t){return Promise.all(t.map((function(t){return e.get(t,(function(){return Promise.resolve(y(t))}))}))).then((function(e){var r=e.filter((function(e){return function(e){return e.status===p||Date.now()-e.lastUpdate>12e4}(e)})),n=e.filter((function(e){return function(e){return e.status===g&&Date.now()-e.lastUpdate<=12e4}(e)})),i=[].concat(a(r),a(n));return{getTimeout:function(e,t){return(0===n.length&&0===e?1:n.length+3+e)*t},statelessHosts:i.length>0?i.map((function(e){return R(e)})):t}}))}function j(e,t,n,i){var s=[],c=function(e,t){if(e.method!==F&&(void 0!==e.data||void 0!==t.data)){var n=Array.isArray(e.data)?e.data:r(r({},e.data),t.data);return JSON.stringify(n)}}(n,i),u=function(e,t){var n=r(r({},e.headers),t.headers),i={};return Object.keys(n).forEach((function(e){var t=n[e];i[e.toLowerCase()]=t})),i}(e,i),o=n.method,h=n.method!==F?{}:r(r({},n.data),i.data),f=r(r(r({"x-algolia-agent":e.userAgent.value},e.queryParameters),h),i.queryParameters),l=0,m=function t(r,a){var h=r.pop();if(void 0===h)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:w(s)};var m={data:c,headers:u,method:o,url:E(h,n.path,f),connectTimeout:a(l,e.timeouts.connect),responseTimeout:a(l,i.timeout)},d=function(e){var t={request:m,response:e,host:h,triesLeft:r.length};return s.push(t),t},p={onSuccess:function(e){return function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e)},onRetry:function(n){var i=d(n);return n.isTimedOut&&l++,Promise.all([e.logger.info("Retryable failure",O(i)),e.hostsCache.set(h,y(h,n.isTimedOut?g:v))]).then((function(){return t(r,a)}))},onFail:function(e){throw d(e),function(e,t){var r=e.content,n=e.status,i=r;try{i=JSON.parse(r).message}catch(e){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(i,n,t)}(e,w(s))}};return e.requester.send(m).then((function(e){return function(e,t){return function(e){var t=e.status;return e.isTimedOut||function(e){var t=e.isTimedOut,r=e.status;return!t&&0==~~r}(e)||2!=~~(t/100)&&4!=~~(t/100)}(e)?t.onRetry(e):2==~~(e.status/100)?t.onSuccess(e):t.onFail(e)}(e,p)}))};return P(e.hostsCache,t).then((function(e){return m(a(e.statelessHosts).reverse(),e.getTimeout)}))}function _(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var r="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(r)&&(t.value="".concat(t.value).concat(r)),t}};return t}function E(e,t,r){var n=x(r),i="".concat(e.protocol,"://").concat(e.url,"/").concat("/"===t.charAt(0)?t.substr(1):t);return n.length&&(i+="?".concat(n)),i}function x(e){return Object.keys(e).map((function(t){return f("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function w(e){return e.map((function(e){return O(e)}))}function O(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return r(r({},e),{},{request:r(r({},e.request),{},{headers:r(r({},e.request.headers),t)})})}var N=function(e){var t=e.appId,n=function(e,t,r){var n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:function(){return e===l.WithinHeaders?n:{}},queryParameters:function(){return e===l.WithinQueryParameters?n:{}}}}(void 0!==e.authMode?e.authMode:l.WithinHeaders,t,e.apiKey),a=function(e){var t=e.hostsCache,r=e.logger,n=e.requester,a=e.requestsCache,s=e.responsesCache,c=e.timeouts,u=e.userAgent,o=e.hosts,h=e.queryParameters,f={hostsCache:t,logger:r,requester:n,requestsCache:a,responsesCache:s,timeouts:c,userAgent:u,headers:e.headers,queryParameters:h,hosts:o.map((function(e){return R(e)})),read:function(e,t){var r=m(t,f.timeouts.read),n=function(){return j(f,f.hosts.filter((function(e){return 0!=(e.accept&d.Read)})),e,r)};if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();var a={request:e,mappedRequestOptions:r,transporter:{queryParameters:f.queryParameters,headers:f.headers}};return f.responsesCache.get(a,(function(){return f.requestsCache.get(a,(function(){return f.requestsCache.set(a,n()).then((function(e){return Promise.all([f.requestsCache.delete(a),e])}),(function(e){return Promise.all([f.requestsCache.delete(a),Promise.reject(e)])})).then((function(e){var t=i(e,2);return t[0],t[1]}))}))}),{miss:function(e){return f.responsesCache.set(a,e)}})},write:function(e,t){return j(f,f.hosts.filter((function(e){return 0!=(e.accept&d.Write)})),e,m(t,f.timeouts.write))}};return f}(r(r({hosts:[{url:"".concat(t,"-dsn.algolia.net"),accept:d.Read},{url:"".concat(t,".algolia.net"),accept:d.Write}].concat(o([{url:"".concat(t,"-1.algolianet.com")},{url:"".concat(t,"-2.algolianet.com")},{url:"".concat(t,"-3.algolianet.com")}]))},e),{},{headers:r(r(r({},n.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:r(r({},n.queryParameters()),e.queryParameters)}));return h({transporter:a,appId:t,addAlgoliaAgent:function(e,t){a.userAgent.add({segment:e,version:t})},clearCache:function(){return Promise.all([a.requestsCache.clear(),a.responsesCache.clear()]).then((function(){}))}},e.methods)},A=function(e){return function(t,r){return t.method===F?e.transporter.read(t,r):e.transporter.write(t,r)}},H=function(e){return function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return h({transporter:e.transporter,appId:e.appId,indexName:t},r.methods)}},S=function(e){return function(t,n){var i=t.map((function(e){return r(r({},e),{},{params:x(e.params||{})})}));return e.transporter.read({method:b,path:"1/indexes/*/queries",data:{requests:i},cacheable:!0},n)}},T=function(e){return function(t,i){return Promise.all(t.map((function(t){var a=t.params,s=a.facetName,c=a.facetQuery,u=n(a,["facetName","facetQuery"]);return H(e)(t.indexName,{methods:{searchForFacetValues:k}}).searchForFacetValues(s,c,r(r({},i),u))})))}},Q=function(e){return function(t,r,n){return e.transporter.read({method:b,path:f("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},n)}},C=function(e){return function(t,r){return e.transporter.read({method:b,path:f("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r)}},k=function(e){return function(t,r,n){return e.transporter.read({method:b,path:f("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n)}},D=1,I=2,q=3;function V(e,t,n){var i,a={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:function(e){return new Promise((function(t){var r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return r.setRequestHeader(t,e.headers[t])}));var n,i=function(e,n){return setTimeout((function(){r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e)},a=i(e.connectTimeout,"Connection timeout");r.onreadystatechange=function(){r.readyState>r.OPENED&&void 0===n&&(clearTimeout(a),n=i(e.responseTimeout,"Socket timeout"))},r.onerror=function(){0===r.status&&(clearTimeout(a),clearTimeout(n),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=function(){clearTimeout(a),clearTimeout(n),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))}},logger:(i=q,{debug:function(e,t){return D>=i&&console.debug(e,t),Promise.resolve()},info:function(e,t){return I>=i&&console.info(e,t),Promise.resolve()},error:function(e,t){return console.error(e,t),Promise.resolve()}}),responsesCache:u(),requestsCache:u({serializable:!1}),hostsCache:c({caches:[s({key:"".concat("4.13.1","-").concat(e)}),u()]}),userAgent:_("4.13.1").add({segment:"Browser",version:"lite"}),authMode:l.WithinQueryParameters};return N(r(r(r({},a),n),{},{methods:{search:S,searchForFacetValues:T,multipleQueries:S,multipleSearchForFacetValues:T,customRequest:A,initIndex:function(e){return function(t){return H(e)(t,{methods:{search:C,searchForFacetValues:k,findAnswers:Q}})}}}}))}return V.version="4.13.1",V}()},4998:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>M});var n=r(7294);function i(e){var t,r,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(r=i(e[t]))&&(n&&(n+=" "),n+=r);else for(t in e)e[t]&&(n&&(n+=" "),n+=t);return n}const a=function(){for(var e,t,r=0,n="";r<arguments.length;)(e=arguments[r++])&&(t=i(e))&&(n&&(n+=" "),n+=t);return n};var s=r(8131),c=r.n(s),u=r(290),o=r.n(u),h=r(412),f=r(5742),l=r(9960),m=r(143),d=r(2263);const p=["zero","one","two","few","many","other"];function v(e){return p.filter((t=>e.includes(t)))}const g={locale:"en",pluralForms:v(["one","other"]),select:e=>1===e?"one":"other"};function y(){const{i18n:{currentLocale:e}}=(0,d.Z)();return(0,n.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:v(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error('Failed to use Intl.PluralRules for locale "'+e+'".\nDocusaurus will fallback to the default (English) implementation.\nError: '+t.message+"\n"),g}}),[e])}function R(){const e=y();return{selectMessage:(t,r)=>function(e,t,r){const n=e.split("|");if(1===n.length)return n[0];n.length>r.pluralForms.length&&console.error("For locale="+r.locale+", a maximum of "+r.pluralForms.length+" plural forms are expected ("+r.pluralForms.join(",")+"), but the message contains "+n.length+": "+e);const i=r.select(t),a=r.pluralForms.indexOf(i);return n[Math.min(a,n.length-1)]}(r,t,e)}}var F=r(6177),b=r(902),P=r(833),j=r(2128),_=r(5999),E=r(6278),x=r(239),w=r(7452);const O="searchQueryInput_u2C7",N="searchVersionInput_m0Ui",A="searchResultsColumn_JPFH",H="algoliaLogo_rT1R",S="algoliaLogoPathFill_WdUC",T="searchResultItem_Tv2o",Q="searchResultItemHeading_KbCB",C="searchResultItemPath_lhe1",k="searchResultItemSummary_AEaO",D="searchQueryColumn_RTkw",I="searchVersionColumn_ypXd",q="searchLogoColumn_rJIA",V="loadingSpinner_XVxU",L="loader_vvXV";function B(e){let{docsSearchVersionsHelpers:t}=e;const r=Object.entries(t.allDocsData).filter((e=>{let[,t]=e;return t.versions.length>1}));return n.createElement("div",{className:a("col","col--3","padding-left--none",I)},r.map((e=>{let[i,a]=e;const s=r.length>1?i+": ":"";return n.createElement("select",{key:i,onChange:e=>t.setSearchVersion(i,e.target.value),defaultValue:t.searchVersions[i],className:N},a.versions.map(((e,t)=>n.createElement("option",{key:t,label:""+s+e.label,value:e.name}))))})))}function z(){const{i18n:{currentLocale:e}}=(0,d.Z)(),{algolia:{appId:t,apiKey:r,indexName:i}}=(0,E.L)(),s=(0,x.l)(),u=function(){const{selectMessage:e}=R();return t=>e(t,(0,_.I)({id:"theme.SearchPage.documentsFound.plurals",description:'Pluralized label for "{count} documents found". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One document found|{count} documents found"},{count:t}))}(),p=function(){const e=(0,m._r)(),[t,r]=(0,n.useState)((()=>Object.entries(e).reduce(((e,t)=>{let[r,n]=t;return{...e,[r]:n.versions[0].name}}),{}))),i=Object.values(e).some((e=>e.versions.length>1));return{allDocsData:e,versioningEnabled:i,searchVersions:t,setSearchVersion:(e,t)=>r((r=>({...r,[e]:t})))}}(),[v,g]=(0,F.K)(),y={items:[],query:null,totalResults:null,totalPages:null,lastPage:null,hasMore:null,loading:null},[P,N]=(0,n.useReducer)(((e,t)=>{switch(t.type){case"reset":return y;case"loading":return{...e,loading:!0};case"update":return v!==t.value.query?e:{...t.value,items:0===t.value.lastPage?t.value.items:e.items.concat(t.value.items)};case"advance":{const t=e.totalPages>e.lastPage+1;return{...e,lastPage:t?e.lastPage+1:e.lastPage,hasMore:t}}default:return e}}),y),I=o()(t,r),z=c()(I,i,{hitsPerPage:15,advancedSyntax:!0,disjunctiveFacets:["language","docusaurus_tag"]});z.on("result",(e=>{let{results:{query:t,hits:r,page:n,nbHits:i,nbPages:a}}=e;if(""===t||!Array.isArray(r))return void N({type:"reset"});const c=e=>e.replace(/algolia-docsearch-suggestion--highlight/g,"search-result-match"),u=r.map((e=>{let{url:t,_highlightResult:{hierarchy:r},_snippetResult:n={}}=e;const i=Object.keys(r).map((e=>c(r[e].value)));return{title:i.pop(),url:s(t),summary:n.content?c(n.content.value)+"...":"",breadcrumbs:i}}));N({type:"update",value:{items:u,query:t,totalResults:i,totalPages:a,lastPage:n,hasMore:a>n+1,loading:!1}})}));const[M,J]=(0,n.useState)(null),W=(0,n.useRef)(0),U=(0,n.useRef)(h.Z.canUseIntersectionObserver&&new IntersectionObserver((e=>{const{isIntersecting:t,boundingClientRect:{y:r}}=e[0];t&&W.current>r&&N({type:"advance"}),W.current=r}),{threshold:1})),Z=()=>v?(0,_.I)({id:"theme.SearchPage.existingResultsTitle",message:'Search results for "{query}"',description:"The search page title for non-empty query"},{query:v}):(0,_.I)({id:"theme.SearchPage.emptyResultsTitle",message:"Search the documentation",description:"The search page title for empty query"}),K=(0,b.zX)((function(t){void 0===t&&(t=0),z.addDisjunctiveFacetRefinement("docusaurus_tag","default"),z.addDisjunctiveFacetRefinement("language",e),Object.entries(p.searchVersions).forEach((e=>{let[t,r]=e;z.addDisjunctiveFacetRefinement("docusaurus_tag","docs-"+t+"-"+r)})),z.setQuery(v).setPage(t).search()}));return(0,n.useEffect)((()=>{if(!M)return;const e=U.current;return e?(e.observe(M),()=>e.unobserve(M)):()=>!0}),[M]),(0,n.useEffect)((()=>{N({type:"reset"}),v&&(N({type:"loading"}),setTimeout((()=>{K()}),300))}),[v,p.searchVersions,K]),(0,n.useEffect)((()=>{P.lastPage&&0!==P.lastPage&&K(P.lastPage)}),[K,P.lastPage]),n.createElement(w.Z,null,n.createElement(f.Z,null,n.createElement("title",null,(0,j.p)(Z())),n.createElement("meta",{property:"robots",content:"noindex, follow"})),n.createElement("div",{className:"container margin-vert--lg"},n.createElement("h1",null,Z()),n.createElement("form",{className:"row",onSubmit:e=>e.preventDefault()},n.createElement("div",{className:a("col",D,{"col--9":p.versioningEnabled,"col--12":!p.versioningEnabled})},n.createElement("input",{type:"search",name:"q",className:O,placeholder:(0,_.I)({id:"theme.SearchPage.inputPlaceholder",message:"Type your search here",description:"The placeholder for search page input"}),"aria-label":(0,_.I)({id:"theme.SearchPage.inputLabel",message:"Search",description:"The ARIA label for search page input"}),onChange:e=>g(e.target.value),value:v,autoComplete:"off",autoFocus:!0})),p.versioningEnabled&&n.createElement(B,{docsSearchVersionsHelpers:p})),n.createElement("div",{className:"row"},n.createElement("div",{className:a("col","col--8",A)},!!P.totalResults&&u(P.totalResults)),n.createElement("div",{className:a("col","col--4","text--right",q)},n.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://www.algolia.com/","aria-label":(0,_.I)({id:"theme.SearchPage.algoliaLabel",message:"Search by Algolia",description:"The ARIA label for Algolia mention"})},n.createElement("svg",{viewBox:"0 0 168 24",className:H},n.createElement("g",{fill:"none"},n.createElement("path",{className:S,d:"M120.925 18.804c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17zM6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z"}),n.createElement("path",{fill:"#5468FF",d:"M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938z"}),n.createElement("path",{fill:"white",d:"M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36"})))))),P.items.length>0?n.createElement("main",null,P.items.map(((e,t)=>{let{title:r,url:i,summary:s,breadcrumbs:c}=e;return n.createElement("article",{key:t,className:T},n.createElement("h2",{className:Q},n.createElement(l.Z,{to:i,dangerouslySetInnerHTML:{__html:r}})),c.length>0&&n.createElement("nav",{"aria-label":"breadcrumbs"},n.createElement("ul",{className:a("breadcrumbs",C)},c.map(((e,t)=>n.createElement("li",{key:t,className:"breadcrumbs__item",dangerouslySetInnerHTML:{__html:e}}))))),s&&n.createElement("p",{className:k,dangerouslySetInnerHTML:{__html:s}}))}))):[v&&!P.loading&&n.createElement("p",{key:"no-results"},n.createElement(_.Z,{id:"theme.SearchPage.noResultsText",description:"The paragraph for empty search result"},"No results were found")),!!P.loading&&n.createElement("div",{key:"spinner",className:V})],P.hasMore&&n.createElement("div",{className:L,ref:J},n.createElement(_.Z,{id:"theme.SearchPage.fetchingNewResults",description:"The paragraph for fetching new search results"},"Fetching new results..."))))}function M(){return n.createElement(P.FG,{className:"search-page-wrapper"},n.createElement(z,null))}}}]); \ No newline at end of file diff --git a/docs/assets/js/1a4e3797.be02ef92.js.LICENSE.txt b/docs/assets/js/1a4e3797.be02ef92.js.LICENSE.txt deleted file mode 100644 index 3016b5c85f..0000000000 --- a/docs/assets/js/1a4e3797.be02ef92.js.LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -/*! algoliasearch-lite.umd.js | 4.13.1 | © Algolia, inc. | https://github.com/algolia/algoliasearch-client-javascript */ diff --git a/docs/assets/js/1a4e3797.cdef43d5.js b/docs/assets/js/1a4e3797.cdef43d5.js new file mode 100644 index 0000000000..17e9d243ff --- /dev/null +++ b/docs/assets/js/1a4e3797.cdef43d5.js @@ -0,0 +1,2 @@ +/*! For license information please see 1a4e3797.cdef43d5.js.LICENSE.txt */ +(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7920],{7331:e=>{function t(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}function i(e){return void 0===e}e.exports=t,t.prototype._events=void 0,t.prototype._maxListeners=void 0,t.defaultMaxListeners=10,t.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw TypeError("n must be a positive number");return this._maxListeners=e,this},t.prototype.emit=function(e){var t,s,a,c,u,o;if(this._events||(this._events={}),"error"===e&&(!this._events.error||n(this._events.error)&&!this._events.error.length)){if((t=arguments[1])instanceof Error)throw t;var h=new Error('Uncaught, unspecified "error" event. ('+t+")");throw h.context=t,h}if(i(s=this._events[e]))return!1;if(r(s))switch(arguments.length){case 1:s.call(this);break;case 2:s.call(this,arguments[1]);break;case 3:s.call(this,arguments[1],arguments[2]);break;default:c=Array.prototype.slice.call(arguments,1),s.apply(this,c)}else if(n(s))for(c=Array.prototype.slice.call(arguments,1),a=(o=s.slice()).length,u=0;u<a;u++)o[u].apply(this,c);return!0},t.prototype.addListener=function(e,s){var a;if(!r(s))throw TypeError("listener must be a function");return this._events||(this._events={}),this._events.newListener&&this.emit("newListener",e,r(s.listener)?s.listener:s),this._events[e]?n(this._events[e])?this._events[e].push(s):this._events[e]=[this._events[e],s]:this._events[e]=s,n(this._events[e])&&!this._events[e].warned&&(a=i(this._maxListeners)?t.defaultMaxListeners:this._maxListeners)&&a>0&&this._events[e].length>a&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t){if(!r(t))throw TypeError("listener must be a function");var n=!1;function i(){this.removeListener(e,i),n||(n=!0,t.apply(this,arguments))}return i.listener=t,this.on(e,i),this},t.prototype.removeListener=function(e,t){var i,s,a,c;if(!r(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(a=(i=this._events[e]).length,s=-1,i===t||r(i.listener)&&i.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(n(i)){for(c=a;c-- >0;)if(i[c]===t||i[c].listener&&i[c].listener===t){s=c;break}if(s<0)return this;1===i.length?(i.length=0,delete this._events[e]):i.splice(s,1),this._events.removeListener&&this.emit("removeListener",e,t)}return this},t.prototype.removeAllListeners=function(e){var t,n;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[e]&&delete this._events[e],this;if(0===arguments.length){for(t in this._events)"removeListener"!==t&&this.removeAllListeners(t);return this.removeAllListeners("removeListener"),this._events={},this}if(r(n=this._events[e]))this.removeListener(e,n);else if(n)for(;n.length;)this.removeListener(e,n[n.length-1]);return delete this._events[e],this},t.prototype.listeners=function(e){return this._events&&this._events[e]?r(this._events[e])?[this._events[e]]:this._events[e].slice():[]},t.prototype.listenerCount=function(e){if(this._events){var t=this._events[e];if(r(t))return 1;if(t)return t.length}return 0},t.listenerCount=function(e,t){return e.listenerCount(t)}},8131:(e,t,r)=>{"use strict";var n=r(9374),i=r(7775),s=r(3076);function a(e,t,r,i){return new n(e,t,r,i)}a.version=r(4336),a.AlgoliaSearchHelper=n,a.SearchParameters=i,a.SearchResults=s,e.exports=a},8078:(e,t,r)=>{"use strict";var n=r(7331);function i(e,t){this.main=e,this.fn=t,this.lastResults=null}r(4853)(i,n),i.prototype.detach=function(){this.removeAllListeners(),this.main.detachDerivedHelper(this)},i.prototype.getModifiedState=function(e){return this.fn(e)},e.exports=i},2437:(e,t,r)=>{"use strict";var n=r(2344),i=r(116),s=r(9803),a={addRefinement:function(e,t,r){if(a.isRefined(e,t,r))return e;var i=""+r,s=e[t]?e[t].concat(i):[i],c={};return c[t]=s,n({},c,e)},removeRefinement:function(e,t,r){if(void 0===r)return a.clearRefinement(e,(function(e,r){return t===r}));var n=""+r;return a.clearRefinement(e,(function(e,r){return t===r&&n===e}))},toggleRefinement:function(e,t,r){if(void 0===r)throw new Error("toggleRefinement should be used with a value");return a.isRefined(e,t,r)?a.removeRefinement(e,t,r):a.addRefinement(e,t,r)},clearRefinement:function(e,t,r){if(void 0===t)return i(e)?{}:e;if("string"==typeof t)return s(e,[t]);if("function"==typeof t){var n=!1,a=Object.keys(e).reduce((function(i,s){var a=e[s]||[],c=a.filter((function(e){return!t(e,s,r)}));return c.length!==a.length&&(n=!0),i[s]=c,i}),{});return n?a:e}},isRefined:function(e,t,r){var n=Boolean(e[t])&&e[t].length>0;if(void 0===r||!n)return n;var i=""+r;return-1!==e[t].indexOf(i)}};e.exports=a},7775:(e,t,r)=>{"use strict";var n=r(2344),i=r(7888),s=r(2686),a=r(185),c=r(116),u=r(9803),o=r(8023),h=r(6801),f=r(2437);function l(e,t){return Array.isArray(e)&&Array.isArray(t)?e.length===t.length&&e.every((function(e,r){return l(t[r],e)})):e===t}function m(e){var t=e?m._parseNumbers(e):{};void 0===t.userToken||h(t.userToken)||console.warn("[algoliasearch-helper] The `userToken` parameter is invalid. This can lead to wrong analytics.\n - Format: [a-zA-Z0-9_-]{1,64}"),this.facets=t.facets||[],this.disjunctiveFacets=t.disjunctiveFacets||[],this.hierarchicalFacets=t.hierarchicalFacets||[],this.facetsRefinements=t.facetsRefinements||{},this.facetsExcludes=t.facetsExcludes||{},this.disjunctiveFacetsRefinements=t.disjunctiveFacetsRefinements||{},this.numericRefinements=t.numericRefinements||{},this.tagRefinements=t.tagRefinements||[],this.hierarchicalFacetsRefinements=t.hierarchicalFacetsRefinements||{};var r=this;Object.keys(t).forEach((function(e){var n=-1!==m.PARAMETERS.indexOf(e),i=void 0!==t[e];!n&&i&&(r[e]=t[e])}))}m.PARAMETERS=Object.keys(new m),m._parseNumbers=function(e){if(e instanceof m)return e;var t={};if(["aroundPrecision","aroundRadius","getRankingInfo","minWordSizefor2Typos","minWordSizefor1Typo","page","maxValuesPerFacet","distinct","minimumAroundRadius","hitsPerPage","minProximity"].forEach((function(r){var n=e[r];if("string"==typeof n){var i=parseFloat(n);t[r]=isNaN(i)?n:i}})),Array.isArray(e.insideBoundingBox)&&(t.insideBoundingBox=e.insideBoundingBox.map((function(e){return Array.isArray(e)?e.map((function(e){return parseFloat(e)})):e}))),e.numericRefinements){var r={};Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t]||{};r[t]={},Object.keys(n).forEach((function(e){var i=n[e].map((function(e){return Array.isArray(e)?e.map((function(e){return"string"==typeof e?parseFloat(e):e})):"string"==typeof e?parseFloat(e):e}));r[t][e]=i}))})),t.numericRefinements=r}return a({},e,t)},m.make=function(e){var t=new m(e);return(e.hierarchicalFacets||[]).forEach((function(e){if(e.rootPath){var r=t.getHierarchicalRefinement(e.name);r.length>0&&0!==r[0].indexOf(e.rootPath)&&(t=t.clearRefinements(e.name)),0===(r=t.getHierarchicalRefinement(e.name)).length&&(t=t.toggleHierarchicalFacetRefinement(e.name,e.rootPath))}})),t},m.validate=function(e,t){var r=t||{};return e.tagFilters&&r.tagRefinements&&r.tagRefinements.length>0?new Error("[Tags] Cannot switch from the managed tag API to the advanced API. It is probably an error, if it is really what you want, you should first clear the tags with clearTags method."):e.tagRefinements.length>0&&r.tagFilters?new Error("[Tags] Cannot switch from the advanced tag API to the managed API. It is probably an error, if it is not, you should first clear the tags with clearTags method."):e.numericFilters&&r.numericRefinements&&c(r.numericRefinements)?new Error("[Numeric filters] Can't switch from the advanced to the managed API. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):c(e.numericRefinements)&&r.numericFilters?new Error("[Numeric filters] Can't switch from the managed API to the advanced. It is probably an error, if this is really what you want, you have to first clear the numeric filters."):null},m.prototype={constructor:m,clearRefinements:function(e){var t={numericRefinements:this._clearNumericRefinements(e),facetsRefinements:f.clearRefinement(this.facetsRefinements,e,"conjunctiveFacet"),facetsExcludes:f.clearRefinement(this.facetsExcludes,e,"exclude"),disjunctiveFacetsRefinements:f.clearRefinement(this.disjunctiveFacetsRefinements,e,"disjunctiveFacet"),hierarchicalFacetsRefinements:f.clearRefinement(this.hierarchicalFacetsRefinements,e,"hierarchicalFacet")};return t.numericRefinements===this.numericRefinements&&t.facetsRefinements===this.facetsRefinements&&t.facetsExcludes===this.facetsExcludes&&t.disjunctiveFacetsRefinements===this.disjunctiveFacetsRefinements&&t.hierarchicalFacetsRefinements===this.hierarchicalFacetsRefinements?this:this.setQueryParameters(t)},clearTags:function(){return void 0===this.tagFilters&&0===this.tagRefinements.length?this:this.setQueryParameters({tagFilters:void 0,tagRefinements:[]})},setIndex:function(e){return e===this.index?this:this.setQueryParameters({index:e})},setQuery:function(e){return e===this.query?this:this.setQueryParameters({query:e})},setPage:function(e){return e===this.page?this:this.setQueryParameters({page:e})},setFacets:function(e){return this.setQueryParameters({facets:e})},setDisjunctiveFacets:function(e){return this.setQueryParameters({disjunctiveFacets:e})},setHitsPerPage:function(e){return this.hitsPerPage===e?this:this.setQueryParameters({hitsPerPage:e})},setTypoTolerance:function(e){return this.typoTolerance===e?this:this.setQueryParameters({typoTolerance:e})},addNumericRefinement:function(e,t,r){var n=o(r);if(this.isNumericRefined(e,t,n))return this;var i=a({},this.numericRefinements);return i[e]=a({},i[e]),i[e][t]?(i[e][t]=i[e][t].slice(),i[e][t].push(n)):i[e][t]=[n],this.setQueryParameters({numericRefinements:i})},getConjunctiveRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsRefinements[e]||[]},getDisjunctiveRefinements:function(e){return this.isDisjunctiveFacet(e)&&this.disjunctiveFacetsRefinements[e]||[]},getHierarchicalRefinement:function(e){return this.hierarchicalFacetsRefinements[e]||[]},getExcludeRefinements:function(e){return this.isConjunctiveFacet(e)&&this.facetsExcludes[e]||[]},removeNumericRefinement:function(e,t,r){var n=r;return void 0!==n?this.isNumericRefined(e,t,n)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(r,i){return i===e&&r.op===t&&l(r.val,o(n))}))}):this:void 0!==t?this.isNumericRefined(e,t)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(r,n){return n===e&&r.op===t}))}):this:this.isNumericRefined(e)?this.setQueryParameters({numericRefinements:this._clearNumericRefinements((function(t,r){return r===e}))}):this},getNumericRefinements:function(e){return this.numericRefinements[e]||{}},getNumericRefinement:function(e,t){return this.numericRefinements[e]&&this.numericRefinements[e][t]},_clearNumericRefinements:function(e){if(void 0===e)return c(this.numericRefinements)?{}:this.numericRefinements;if("string"==typeof e)return u(this.numericRefinements,[e]);if("function"==typeof e){var t=!1,r=this.numericRefinements,n=Object.keys(r).reduce((function(n,i){var s=r[i],a={};return s=s||{},Object.keys(s).forEach((function(r){var n=s[r]||[],c=[];n.forEach((function(t){e({val:t,op:r},i,"numeric")||c.push(t)})),c.length!==n.length&&(t=!0),a[r]=c})),n[i]=a,n}),{});return t?n:this.numericRefinements}},addFacet:function(e){return this.isConjunctiveFacet(e)?this:this.setQueryParameters({facets:this.facets.concat([e])})},addDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this:this.setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.concat([e])})},addHierarchicalFacet:function(e){if(this.isHierarchicalFacet(e.name))throw new Error("Cannot declare two hierarchical facets with the same name: `"+e.name+"`");return this.setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.concat([e])})},addFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsRefinements,e,t)?this:this.setQueryParameters({facetsRefinements:f.addRefinement(this.facetsRefinements,e,t)})},addExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsExcludes,e,t)?this:this.setQueryParameters({facetsExcludes:f.addRefinement(this.facetsExcludes,e,t)})},addDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return f.isRefined(this.disjunctiveFacetsRefinements,e,t)?this:this.setQueryParameters({disjunctiveFacetsRefinements:f.addRefinement(this.disjunctiveFacetsRefinements,e,t)})},addTagRefinement:function(e){if(this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.concat(e)};return this.setQueryParameters(t)},removeFacet:function(e){return this.isConjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({facets:this.facets.filter((function(t){return t!==e}))}):this},removeDisjunctiveFacet:function(e){return this.isDisjunctiveFacet(e)?this.clearRefinements(e).setQueryParameters({disjunctiveFacets:this.disjunctiveFacets.filter((function(t){return t!==e}))}):this},removeHierarchicalFacet:function(e){return this.isHierarchicalFacet(e)?this.clearRefinements(e).setQueryParameters({hierarchicalFacets:this.hierarchicalFacets.filter((function(t){return t.name!==e}))}):this},removeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsRefinements,e,t)?this.setQueryParameters({facetsRefinements:f.removeRefinement(this.facetsRefinements,e,t)}):this},removeExcludeRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return f.isRefined(this.facetsExcludes,e,t)?this.setQueryParameters({facetsExcludes:f.removeRefinement(this.facetsExcludes,e,t)}):this},removeDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return f.isRefined(this.disjunctiveFacetsRefinements,e,t)?this.setQueryParameters({disjunctiveFacetsRefinements:f.removeRefinement(this.disjunctiveFacetsRefinements,e,t)}):this},removeTagRefinement:function(e){if(!this.isTagRefined(e))return this;var t={tagRefinements:this.tagRefinements.filter((function(t){return t!==e}))};return this.setQueryParameters(t)},toggleRefinement:function(e,t){return this.toggleFacetRefinement(e,t)},toggleFacetRefinement:function(e,t){if(this.isHierarchicalFacet(e))return this.toggleHierarchicalFacetRefinement(e,t);if(this.isConjunctiveFacet(e))return this.toggleConjunctiveFacetRefinement(e,t);if(this.isDisjunctiveFacet(e))return this.toggleDisjunctiveFacetRefinement(e,t);throw new Error("Cannot refine the undeclared facet "+e+"; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets")},toggleConjunctiveFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsRefinements:f.toggleRefinement(this.facetsRefinements,e,t)})},toggleExcludeFacetRefinement:function(e,t){if(!this.isConjunctiveFacet(e))throw new Error(e+" is not defined in the facets attribute of the helper configuration");return this.setQueryParameters({facetsExcludes:f.toggleRefinement(this.facetsExcludes,e,t)})},toggleDisjunctiveFacetRefinement:function(e,t){if(!this.isDisjunctiveFacet(e))throw new Error(e+" is not defined in the disjunctiveFacets attribute of the helper configuration");return this.setQueryParameters({disjunctiveFacetsRefinements:f.toggleRefinement(this.disjunctiveFacetsRefinements,e,t)})},toggleHierarchicalFacetRefinement:function(e,t){if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration");var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e)),i={};return void 0!==this.hierarchicalFacetsRefinements[e]&&this.hierarchicalFacetsRefinements[e].length>0&&(this.hierarchicalFacetsRefinements[e][0]===t||0===this.hierarchicalFacetsRefinements[e][0].indexOf(t+r))?-1===t.indexOf(r)?i[e]=[]:i[e]=[t.slice(0,t.lastIndexOf(r))]:i[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:n({},i,this.hierarchicalFacetsRefinements)})},addHierarchicalFacetRefinement:function(e,t){if(this.isHierarchicalFacetRefined(e))throw new Error(e+" is already refined.");if(!this.isHierarchicalFacet(e))throw new Error(e+" is not defined in the hierarchicalFacets attribute of the helper configuration.");var r={};return r[e]=[t],this.setQueryParameters({hierarchicalFacetsRefinements:n({},r,this.hierarchicalFacetsRefinements)})},removeHierarchicalFacetRefinement:function(e){if(!this.isHierarchicalFacetRefined(e))return this;var t={};return t[e]=[],this.setQueryParameters({hierarchicalFacetsRefinements:n({},t,this.hierarchicalFacetsRefinements)})},toggleTagRefinement:function(e){return this.isTagRefined(e)?this.removeTagRefinement(e):this.addTagRefinement(e)},isDisjunctiveFacet:function(e){return this.disjunctiveFacets.indexOf(e)>-1},isHierarchicalFacet:function(e){return void 0!==this.getHierarchicalFacetByName(e)},isConjunctiveFacet:function(e){return this.facets.indexOf(e)>-1},isFacetRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&f.isRefined(this.facetsRefinements,e,t)},isExcludeRefined:function(e,t){return!!this.isConjunctiveFacet(e)&&f.isRefined(this.facetsExcludes,e,t)},isDisjunctiveFacetRefined:function(e,t){return!!this.isDisjunctiveFacet(e)&&f.isRefined(this.disjunctiveFacetsRefinements,e,t)},isHierarchicalFacetRefined:function(e,t){if(!this.isHierarchicalFacet(e))return!1;var r=this.getHierarchicalRefinement(e);return t?-1!==r.indexOf(t):r.length>0},isNumericRefined:function(e,t,r){if(void 0===r&&void 0===t)return Boolean(this.numericRefinements[e]);var n=this.numericRefinements[e]&&void 0!==this.numericRefinements[e][t];if(void 0===r||!n)return n;var s,a,c=o(r),u=void 0!==(s=this.numericRefinements[e][t],a=c,i(s,(function(e){return l(e,a)})));return n&&u},isTagRefined:function(e){return-1!==this.tagRefinements.indexOf(e)},getRefinedDisjunctiveFacets:function(){var e=this,t=s(Object.keys(this.numericRefinements).filter((function(t){return Object.keys(e.numericRefinements[t]).length>0})),this.disjunctiveFacets);return Object.keys(this.disjunctiveFacetsRefinements).filter((function(t){return e.disjunctiveFacetsRefinements[t].length>0})).concat(t).concat(this.getRefinedHierarchicalFacets()).sort()},getRefinedHierarchicalFacets:function(){var e=this;return s(this.hierarchicalFacets.map((function(e){return e.name})),Object.keys(this.hierarchicalFacetsRefinements).filter((function(t){return e.hierarchicalFacetsRefinements[t].length>0}))).sort()},getUnrefinedDisjunctiveFacets:function(){var e=this.getRefinedDisjunctiveFacets();return this.disjunctiveFacets.filter((function(t){return-1===e.indexOf(t)}))},managedParameters:["index","facets","disjunctiveFacets","facetsRefinements","hierarchicalFacets","facetsExcludes","disjunctiveFacetsRefinements","numericRefinements","tagRefinements","hierarchicalFacetsRefinements"],getQueryParams:function(){var e=this.managedParameters,t={},r=this;return Object.keys(this).forEach((function(n){var i=r[n];-1===e.indexOf(n)&&void 0!==i&&(t[n]=i)})),t},setQueryParameter:function(e,t){if(this[e]===t)return this;var r={};return r[e]=t,this.setQueryParameters(r)},setQueryParameters:function(e){if(!e)return this;var t=m.validate(this,e);if(t)throw t;var r=this,n=m._parseNumbers(e),i=Object.keys(this).reduce((function(e,t){return e[t]=r[t],e}),{}),s=Object.keys(n).reduce((function(e,t){var r=void 0!==e[t],i=void 0!==n[t];return r&&!i?u(e,[t]):(i&&(e[t]=n[t]),e)}),i);return new this.constructor(s)},resetPage:function(){return void 0===this.page?this:this.setPage(0)},_getHierarchicalFacetSortBy:function(e){return e.sortBy||["isRefined:desc","name:asc"]},_getHierarchicalFacetSeparator:function(e){return e.separator||" > "},_getHierarchicalRootPath:function(e){return e.rootPath||null},_getHierarchicalShowParentLevel:function(e){return"boolean"!=typeof e.showParentLevel||e.showParentLevel},getHierarchicalFacetByName:function(e){return i(this.hierarchicalFacets,(function(t){return t.name===e}))},getHierarchicalFacetBreadcrumb:function(e){if(!this.isHierarchicalFacet(e))return[];var t=this.getHierarchicalRefinement(e)[0];if(!t)return[];var r=this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(e));return t.split(r).map((function(e){return e.trim()}))},toString:function(){return JSON.stringify(this,null,2)}},e.exports=m},210:(e,t,r)=>{"use strict";e.exports=function(e){return function(t,r){var n=e.hierarchicalFacets[r],o=e.hierarchicalFacetsRefinements[n.name]&&e.hierarchicalFacetsRefinements[n.name][0]||"",h=e._getHierarchicalFacetSeparator(n),f=e._getHierarchicalRootPath(n),l=e._getHierarchicalShowParentLevel(n),m=s(e._getHierarchicalFacetSortBy(n)),d=t.every((function(e){return e.exhaustive})),p=function(e,t,r,n,s){return function(o,h,f){var l=o;if(f>0){var m=0;for(l=o;m<f;){var d=l&&Array.isArray(l.data)?l.data:[];l=i(d,(function(e){return e.isRefined})),m++}}if(l){var p=Object.keys(h.data).map((function(e){return[e,h.data[e]]})).filter((function(e){return function(e,t,r,n,i,s){if(i&&(0!==e.indexOf(i)||i===e))return!1;return!i&&-1===e.indexOf(n)||i&&e.split(n).length-i.split(n).length==1||-1===e.indexOf(n)&&-1===r.indexOf(n)||0===r.indexOf(e)||0===e.indexOf(t+n)&&(s||0===e.indexOf(r))}(e[0],l.path||r,s,t,r,n)}));l.data=a(p.map((function(e){var r=e[0];return function(e,t,r,n,i){var s=t.split(r);return{name:s[s.length-1].trim(),path:t,escapedValue:c(t),count:e,isRefined:n===t||0===n.indexOf(t+r),exhaustive:i,data:null}}(e[1],r,t,u(s),h.exhaustive)})),e[0],e[1])}return o}}(m,h,f,l,o),v=t;return f&&(v=t.slice(f.split(h).length)),v.reduce(p,{name:e.hierarchicalFacets[r].name,count:null,isRefined:!0,path:null,escapedValue:null,exhaustive:d,data:null})}};var n=r(4039),i=r(7888),s=r(2293),a=r(2148),c=n.escapeFacetValue,u=n.unescapeFacetValue},3076:(e,t,r)=>{"use strict";var n=r(4587),i=r(2344),s=r(4039),a=r(7888),c=r(9725),u=r(2293),o=r(185),h=r(2148),f=s.escapeFacetValue,l=s.unescapeFacetValue,m=r(210);function d(e){var t={};return e.forEach((function(e,r){t[e]=r})),t}function p(e,t,r){t&&t[r]&&(e.stats=t[r])}function v(e,t,r){var s=t[0];this._rawResults=t;var u=this;Object.keys(s).forEach((function(e){u[e]=s[e]}));var h=o({persistHierarchicalRootCount:!1},r);Object.keys(h).forEach((function(e){u[e]=h[e]})),this.processingTimeMS=t.reduce((function(e,t){return void 0===t.processingTimeMS?e:e+t.processingTimeMS}),0),this.disjunctiveFacets=[],this.hierarchicalFacets=e.hierarchicalFacets.map((function(){return[]})),this.facets=[];var f=e.getRefinedDisjunctiveFacets(),v=d(e.facets),g=d(e.disjunctiveFacets),y=1,R=s.facets||{};Object.keys(R).forEach((function(t){var r,n,i=R[t],o=(r=e.hierarchicalFacets,n=t,a(r,(function(e){return(e.attributes||[]).indexOf(n)>-1})));if(o){var h=o.attributes.indexOf(t),f=c(e.hierarchicalFacets,(function(e){return e.name===o.name}));u.hierarchicalFacets[f][h]={attribute:t,data:i,exhaustive:s.exhaustiveFacetsCount}}else{var l,m=-1!==e.disjunctiveFacets.indexOf(t),d=-1!==e.facets.indexOf(t);m&&(l=g[t],u.disjunctiveFacets[l]={name:t,data:i,exhaustive:s.exhaustiveFacetsCount},p(u.disjunctiveFacets[l],s.facets_stats,t)),d&&(l=v[t],u.facets[l]={name:t,data:i,exhaustive:s.exhaustiveFacetsCount},p(u.facets[l],s.facets_stats,t))}})),this.hierarchicalFacets=n(this.hierarchicalFacets),f.forEach((function(r){var n=t[y],a=n&&n.facets?n.facets:{},h=e.getHierarchicalFacetByName(r);Object.keys(a).forEach((function(t){var r,f=a[t];if(h){r=c(e.hierarchicalFacets,(function(e){return e.name===h.name}));var m=c(u.hierarchicalFacets[r],(function(e){return e.attribute===t}));if(-1===m)return;u.hierarchicalFacets[r][m].data=o({},u.hierarchicalFacets[r][m].data,f)}else{r=g[t];var d=s.facets&&s.facets[t]||{};u.disjunctiveFacets[r]={name:t,data:i({},f,d),exhaustive:n.exhaustiveFacetsCount},p(u.disjunctiveFacets[r],n.facets_stats,t),e.disjunctiveFacetsRefinements[t]&&e.disjunctiveFacetsRefinements[t].forEach((function(n){!u.disjunctiveFacets[r].data[n]&&e.disjunctiveFacetsRefinements[t].indexOf(l(n))>-1&&(u.disjunctiveFacets[r].data[n]=0)}))}})),y++})),e.getRefinedHierarchicalFacets().forEach((function(r){var n=e.getHierarchicalFacetByName(r),s=e._getHierarchicalFacetSeparator(n),a=e.getHierarchicalRefinement(r);0===a.length||a[0].split(s).length<2||t.slice(y).forEach((function(t){var r=t&&t.facets?t.facets:{};Object.keys(r).forEach((function(t){var o=r[t],h=c(e.hierarchicalFacets,(function(e){return e.name===n.name})),f=c(u.hierarchicalFacets[h],(function(e){return e.attribute===t}));if(-1!==f){var l={};if(a.length>0&&!u.persistHierarchicalRootCount){var m=a[0].split(s)[0];l[m]=u.hierarchicalFacets[h][f].data[m]}u.hierarchicalFacets[h][f].data=i(l,o,u.hierarchicalFacets[h][f].data)}})),y++}))})),Object.keys(e.facetsExcludes).forEach((function(t){var r=e.facetsExcludes[t],n=v[t];u.facets[n]={name:t,data:R[t],exhaustive:s.exhaustiveFacetsCount},r.forEach((function(e){u.facets[n]=u.facets[n]||{name:t},u.facets[n].data=u.facets[n].data||{},u.facets[n].data[e]=0}))})),this.hierarchicalFacets=this.hierarchicalFacets.map(m(e)),this.facets=n(this.facets),this.disjunctiveFacets=n(this.disjunctiveFacets),this._state=e}function g(e,t){function r(e){return e.name===t}if(e._state.isConjunctiveFacet(t)){var n=a(e.facets,r);return n?Object.keys(n.data).map((function(r){var i=f(r);return{name:r,escapedValue:i,count:n.data[r],isRefined:e._state.isFacetRefined(t,i),isExcluded:e._state.isExcludeRefined(t,r)}})):[]}if(e._state.isDisjunctiveFacet(t)){var i=a(e.disjunctiveFacets,r);return i?Object.keys(i.data).map((function(r){var n=f(r);return{name:r,escapedValue:n,count:i.data[r],isRefined:e._state.isDisjunctiveFacetRefined(t,n)}})):[]}if(e._state.isHierarchicalFacet(t)){var s=a(e.hierarchicalFacets,r);if(!s)return s;var c=e._state.getHierarchicalFacetByName(t),u=e._state._getHierarchicalFacetSeparator(c),o=l(e._state.getHierarchicalRefinement(t)[0]||"");0===o.indexOf(c.rootPath)&&(o=o.replace(c.rootPath+u,""));var h=o.split(u);return h.unshift(t),y(s,h,0),s}}function y(e,t,r){e.isRefined=e.name===t[r],e.data&&e.data.forEach((function(e){y(e,t,r+1)}))}function R(e,t,r,n){if(n=n||0,Array.isArray(t))return e(t,r[n]);if(!t.data||0===t.data.length)return t;var s=t.data.map((function(t){return R(e,t,r,n+1)})),a=e(s,r[n]);return i({data:a},t)}function F(e,t){var r=a(e,(function(e){return e.name===t}));return r&&r.stats}function b(e,t,r,n,i){var s=a(i,(function(e){return e.name===r})),c=s&&s.data&&s.data[n]?s.data[n]:0,u=s&&s.exhaustive||!1;return{type:t,attributeName:r,name:n,count:c,exhaustive:u}}v.prototype.getFacetByName=function(e){function t(t){return t.name===e}return a(this.facets,t)||a(this.disjunctiveFacets,t)||a(this.hierarchicalFacets,t)},v.DEFAULT_SORT=["isRefined:desc","count:desc","name:asc"],v.prototype.getFacetValues=function(e,t){var r=g(this,e);if(r){var n,s=i({},t,{sortBy:v.DEFAULT_SORT,facetOrdering:!(t&&t.sortBy)}),a=this;if(Array.isArray(r))n=[e];else n=a._state.getHierarchicalFacetByName(r.name).attributes;return R((function(e,t){if(s.facetOrdering){var r=function(e,t){return e.renderingContent&&e.renderingContent.facetOrdering&&e.renderingContent.facetOrdering.values&&e.renderingContent.facetOrdering.values[t]}(a,t);if(r)return function(e,t){var r=[],n=[],i=(t.order||[]).reduce((function(e,t,r){return e[t]=r,e}),{});e.forEach((function(e){var t=e.path||e.name;void 0!==i[t]?r[i[t]]=e:n.push(e)})),r=r.filter((function(e){return e}));var s,a=t.sortRemainingBy;return"hidden"===a?r:(s="alpha"===a?[["path","name"],["asc","asc"]]:[["count"],["desc"]],r.concat(h(n,s[0],s[1])))}(e,r)}if(Array.isArray(s.sortBy)){var n=u(s.sortBy,v.DEFAULT_SORT);return h(e,n[0],n[1])}if("function"==typeof s.sortBy)return function(e,t){return t.sort(e)}(s.sortBy,e);throw new Error("options.sortBy is optional but if defined it must be either an array of string (predicates) or a sorting function")}),r,n)}},v.prototype.getFacetStats=function(e){return this._state.isConjunctiveFacet(e)?F(this.facets,e):this._state.isDisjunctiveFacet(e)?F(this.disjunctiveFacets,e):void 0},v.prototype.getRefinements=function(){var e=this._state,t=this,r=[];return Object.keys(e.facetsRefinements).forEach((function(n){e.facetsRefinements[n].forEach((function(i){r.push(b(e,"facet",n,i,t.facets))}))})),Object.keys(e.facetsExcludes).forEach((function(n){e.facetsExcludes[n].forEach((function(i){r.push(b(e,"exclude",n,i,t.facets))}))})),Object.keys(e.disjunctiveFacetsRefinements).forEach((function(n){e.disjunctiveFacetsRefinements[n].forEach((function(i){r.push(b(e,"disjunctive",n,i,t.disjunctiveFacets))}))})),Object.keys(e.hierarchicalFacetsRefinements).forEach((function(n){e.hierarchicalFacetsRefinements[n].forEach((function(i){r.push(function(e,t,r,n){var i=e.getHierarchicalFacetByName(t),s=e._getHierarchicalFacetSeparator(i),c=r.split(s),u=a(n,(function(e){return e.name===t})),o=c.reduce((function(e,t){var r=e&&a(e.data,(function(e){return e.name===t}));return void 0!==r?r:e}),u),h=o&&o.count||0,f=o&&o.exhaustive||!1,l=o&&o.path||"";return{type:"hierarchical",attributeName:t,name:l,count:h,exhaustive:f}}(e,n,i,t.hierarchicalFacets))}))})),Object.keys(e.numericRefinements).forEach((function(t){var n=e.numericRefinements[t];Object.keys(n).forEach((function(e){n[e].forEach((function(n){r.push({type:"numeric",attributeName:t,name:n,numericValue:n,operator:e})}))}))})),e.tagRefinements.forEach((function(e){r.push({type:"tag",attributeName:"_tags",name:e})})),r},e.exports=v},9374:(e,t,r)=>{"use strict";var n=r(7331),i=r(8078),s=r(4039).escapeFacetValue,a=r(4853),c=r(185),u=r(116),o=r(9803),h=r(6394),f=r(7775),l=r(3076),m=r(4336);function d(e,t,r,n){"function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+m+")"),this.setClient(e);var i=r||{};i.index=t,this.state=f.make(i),this.lastResults=null,this._queryId=0,this._lastQueryIdReceived=-1,this.derivedHelpers=[],this._currentNbQueries=0,this._searchResultsOptions=n}function p(e){if(e<0)throw new Error("Page requested below 0.");return this._change({state:this.state.setPage(e),isPageReset:!1}),this}function v(){return this.state.page}a(d,n),d.prototype.search=function(){return this._search({onlyWithDerivedHelpers:!1}),this},d.prototype.searchOnlyWithDerivedHelpers=function(){return this._search({onlyWithDerivedHelpers:!0}),this},d.prototype.getQuery=function(){var e=this.state;return h._getHitsSearchParams(e)},d.prototype.searchOnce=function(e,t){var r=e?this.state.setQueryParameters(e):this.state,n=h._getQueries(r.index,r),i=this;if(this._currentNbQueries++,this.emit("searchOnce",{state:r}),!t)return this.client.search(n).then((function(e){return i._currentNbQueries--,0===i._currentNbQueries&&i.emit("searchQueueEmpty"),{content:new l(r,e.results),state:r,_originalResponse:e}}),(function(e){throw i._currentNbQueries--,0===i._currentNbQueries&&i.emit("searchQueueEmpty"),e}));this.client.search(n).then((function(e){i._currentNbQueries--,0===i._currentNbQueries&&i.emit("searchQueueEmpty"),t(null,new l(r,e.results),r)})).catch((function(e){i._currentNbQueries--,0===i._currentNbQueries&&i.emit("searchQueueEmpty"),t(e,null,r)}))},d.prototype.findAnswers=function(e){console.warn("[algoliasearch-helper] answers is no longer supported");var t=this.state,r=this.derivedHelpers[0];if(!r)return Promise.resolve([]);var n=r.getModifiedState(t),i=c({attributesForPrediction:e.attributesForPrediction,nbHits:e.nbHits},{params:o(h._getHitsSearchParams(n),["attributesToSnippet","hitsPerPage","restrictSearchableAttributes","snippetEllipsisText"])}),s="search for answers was called, but this client does not have a function client.initIndex(index).findAnswers";if("function"!=typeof this.client.initIndex)throw new Error(s);var a=this.client.initIndex(n.index);if("function"!=typeof a.findAnswers)throw new Error(s);return a.findAnswers(n.query,e.queryLanguages,i)},d.prototype.searchForFacetValues=function(e,t,r,n){var i="function"==typeof this.client.searchForFacetValues,a="function"==typeof this.client.initIndex;if(!i&&!a&&"function"!=typeof this.client.search)throw new Error("search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues or client.initIndex(index).searchForFacetValues");var c=this.state.setQueryParameters(n||{}),u=c.isDisjunctiveFacet(e),o=h.getSearchForFacetQuery(e,t,r,c);this._currentNbQueries++;var f,l=this;return i?f=this.client.searchForFacetValues([{indexName:c.index,params:o}]):a?f=this.client.initIndex(c.index).searchForFacetValues(o):(delete o.facetName,f=this.client.search([{type:"facet",facet:e,indexName:c.index,params:o}]).then((function(e){return e.results[0]}))),this.emit("searchForFacetValues",{state:c,facet:e,query:t}),f.then((function(t){return l._currentNbQueries--,0===l._currentNbQueries&&l.emit("searchQueueEmpty"),(t=Array.isArray(t)?t[0]:t).facetHits.forEach((function(t){t.escapedValue=s(t.value),t.isRefined=u?c.isDisjunctiveFacetRefined(e,t.escapedValue):c.isFacetRefined(e,t.escapedValue)})),t}),(function(e){throw l._currentNbQueries--,0===l._currentNbQueries&&l.emit("searchQueueEmpty"),e}))},d.prototype.setQuery=function(e){return this._change({state:this.state.resetPage().setQuery(e),isPageReset:!0}),this},d.prototype.clearRefinements=function(e){return this._change({state:this.state.resetPage().clearRefinements(e),isPageReset:!0}),this},d.prototype.clearTags=function(){return this._change({state:this.state.resetPage().clearTags(),isPageReset:!0}),this},d.prototype.addDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addDisjunctiveRefine=function(){return this.addDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.addHierarchicalFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addHierarchicalFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().addNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.addFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().addFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.addRefine=function(){return this.addFacetRefinement.apply(this,arguments)},d.prototype.addFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().addExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.addExclude=function(){return this.addFacetExclusion.apply(this,arguments)},d.prototype.addTag=function(e){return this._change({state:this.state.resetPage().addTagRefinement(e),isPageReset:!0}),this},d.prototype.removeNumericRefinement=function(e,t,r){return this._change({state:this.state.resetPage().removeNumericRefinement(e,t,r),isPageReset:!0}),this},d.prototype.removeDisjunctiveFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeDisjunctiveFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeDisjunctiveRefine=function(){return this.removeDisjunctiveFacetRefinement.apply(this,arguments)},d.prototype.removeHierarchicalFacetRefinement=function(e){return this._change({state:this.state.resetPage().removeHierarchicalFacetRefinement(e),isPageReset:!0}),this},d.prototype.removeFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().removeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.removeRefine=function(){return this.removeFacetRefinement.apply(this,arguments)},d.prototype.removeFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().removeExcludeRefinement(e,t),isPageReset:!0}),this},d.prototype.removeExclude=function(){return this.removeFacetExclusion.apply(this,arguments)},d.prototype.removeTag=function(e){return this._change({state:this.state.resetPage().removeTagRefinement(e),isPageReset:!0}),this},d.prototype.toggleFacetExclusion=function(e,t){return this._change({state:this.state.resetPage().toggleExcludeFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleExclude=function(){return this.toggleFacetExclusion.apply(this,arguments)},d.prototype.toggleRefinement=function(e,t){return this.toggleFacetRefinement(e,t)},d.prototype.toggleFacetRefinement=function(e,t){return this._change({state:this.state.resetPage().toggleFacetRefinement(e,t),isPageReset:!0}),this},d.prototype.toggleRefine=function(){return this.toggleFacetRefinement.apply(this,arguments)},d.prototype.toggleTag=function(e){return this._change({state:this.state.resetPage().toggleTagRefinement(e),isPageReset:!0}),this},d.prototype.nextPage=function(){var e=this.state.page||0;return this.setPage(e+1)},d.prototype.previousPage=function(){var e=this.state.page||0;return this.setPage(e-1)},d.prototype.setCurrentPage=p,d.prototype.setPage=p,d.prototype.setIndex=function(e){return this._change({state:this.state.resetPage().setIndex(e),isPageReset:!0}),this},d.prototype.setQueryParameter=function(e,t){return this._change({state:this.state.resetPage().setQueryParameter(e,t),isPageReset:!0}),this},d.prototype.setState=function(e){return this._change({state:f.make(e),isPageReset:!1}),this},d.prototype.overrideStateWithoutTriggeringChangeEvent=function(e){return this.state=new f(e),this},d.prototype.hasRefinements=function(e){return!!u(this.state.getNumericRefinements(e))||(this.state.isConjunctiveFacet(e)?this.state.isFacetRefined(e):this.state.isDisjunctiveFacet(e)?this.state.isDisjunctiveFacetRefined(e):!!this.state.isHierarchicalFacet(e)&&this.state.isHierarchicalFacetRefined(e))},d.prototype.isExcluded=function(e,t){return this.state.isExcludeRefined(e,t)},d.prototype.isDisjunctiveRefined=function(e,t){return this.state.isDisjunctiveFacetRefined(e,t)},d.prototype.hasTag=function(e){return this.state.isTagRefined(e)},d.prototype.isTagRefined=function(){return this.hasTagRefinements.apply(this,arguments)},d.prototype.getIndex=function(){return this.state.index},d.prototype.getCurrentPage=v,d.prototype.getPage=v,d.prototype.getTags=function(){return this.state.tagRefinements},d.prototype.getRefinements=function(e){var t=[];if(this.state.isConjunctiveFacet(e))this.state.getConjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"conjunctive"})})),this.state.getExcludeRefinements(e).forEach((function(e){t.push({value:e,type:"exclude"})}));else if(this.state.isDisjunctiveFacet(e)){this.state.getDisjunctiveRefinements(e).forEach((function(e){t.push({value:e,type:"disjunctive"})}))}var r=this.state.getNumericRefinements(e);return Object.keys(r).forEach((function(e){var n=r[e];t.push({value:n,operator:e,type:"numeric"})})),t},d.prototype.getNumericRefinement=function(e,t){return this.state.getNumericRefinement(e,t)},d.prototype.getHierarchicalFacetBreadcrumb=function(e){return this.state.getHierarchicalFacetBreadcrumb(e)},d.prototype._search=function(e){var t=this.state,r=[],n=[];e.onlyWithDerivedHelpers||(n=h._getQueries(t.index,t),r.push({state:t,queriesCount:n.length,helper:this}),this.emit("search",{state:t,results:this.lastResults}));var i=this.derivedHelpers.map((function(e){var n=e.getModifiedState(t),i=n.index?h._getQueries(n.index,n):[];return r.push({state:n,queriesCount:i.length,helper:e}),e.emit("search",{state:n,results:e.lastResults}),i})),s=Array.prototype.concat.apply(n,i),a=this._queryId++;if(this._currentNbQueries++,!s.length)return Promise.resolve({results:[]}).then(this._dispatchAlgoliaResponse.bind(this,r,a));try{this.client.search(s).then(this._dispatchAlgoliaResponse.bind(this,r,a)).catch(this._dispatchAlgoliaError.bind(this,a))}catch(c){this.emit("error",{error:c})}},d.prototype._dispatchAlgoliaResponse=function(e,t,r){var n=this;if(!(t<this._lastQueryIdReceived)){this._currentNbQueries-=t-this._lastQueryIdReceived,this._lastQueryIdReceived=t,0===this._currentNbQueries&&this.emit("searchQueueEmpty");var i=r.results.slice();e.forEach((function(e){var t=e.state,r=e.queriesCount,s=e.helper,a=i.splice(0,r);t.index?(s.lastResults=new l(t,a,n._searchResultsOptions),s.emit("result",{results:s.lastResults,state:t})):s.emit("result",{results:null,state:t})}))}},d.prototype._dispatchAlgoliaError=function(e,t){e<this._lastQueryIdReceived||(this._currentNbQueries-=e-this._lastQueryIdReceived,this._lastQueryIdReceived=e,this.emit("error",{error:t}),0===this._currentNbQueries&&this.emit("searchQueueEmpty"))},d.prototype.containsRefinement=function(e,t,r,n){return e||0!==t.length||0!==r.length||0!==n.length},d.prototype._hasDisjunctiveRefinements=function(e){return this.state.disjunctiveRefinements[e]&&this.state.disjunctiveRefinements[e].length>0},d.prototype._change=function(e){var t=e.state,r=e.isPageReset;t!==this.state&&(this.state=t,this.emit("change",{state:this.state,results:this.lastResults,isPageReset:r}))},d.prototype.clearCache=function(){return this.client.clearCache&&this.client.clearCache(),this},d.prototype.setClient=function(e){return this.client===e||("function"==typeof e.addAlgoliaAgent&&e.addAlgoliaAgent("JS Helper ("+m+")"),this.client=e),this},d.prototype.getClient=function(){return this.client},d.prototype.derive=function(e){var t=new i(this,e);return this.derivedHelpers.push(t),t},d.prototype.detachDerivedHelper=function(e){var t=this.derivedHelpers.indexOf(e);if(-1===t)throw new Error("Derived helper already detached");this.derivedHelpers.splice(t,1)},d.prototype.hasPendingRequests=function(){return this._currentNbQueries>0},e.exports=d},4587:e=>{"use strict";e.exports=function(e){return Array.isArray(e)?e.filter(Boolean):[]}},2344:e=>{"use strict";e.exports=function(){return Array.prototype.slice.call(arguments).reduceRight((function(e,t){return Object.keys(Object(t)).forEach((function(r){void 0!==t[r]&&(void 0!==e[r]&&delete e[r],e[r]=t[r])})),e}),{})}},4039:e=>{"use strict";e.exports={escapeFacetValue:function(e){return"string"!=typeof e?e:String(e).replace(/^-/,"\\-")},unescapeFacetValue:function(e){return"string"!=typeof e?e:e.replace(/^\\-/,"-")}}},7888:e=>{"use strict";e.exports=function(e,t){if(Array.isArray(e))for(var r=0;r<e.length;r++)if(t(e[r]))return e[r]}},9725:e=>{"use strict";e.exports=function(e,t){if(!Array.isArray(e))return-1;for(var r=0;r<e.length;r++)if(t(e[r]))return r;return-1}},2293:(e,t,r)=>{"use strict";var n=r(7888);e.exports=function(e,t){var r=(t||[]).map((function(e){return e.split(":")}));return e.reduce((function(e,t){var i=t.split(":"),s=n(r,(function(e){return e[0]===i[0]}));return i.length>1||!s?(e[0].push(i[0]),e[1].push(i[1]),e):(e[0].push(s[0]),e[1].push(s[1]),e)}),[[],[]])}},4853:e=>{"use strict";e.exports=function(e,t){e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}},2686:e=>{"use strict";e.exports=function(e,t){return e.filter((function(r,n){return t.indexOf(r)>-1&&e.indexOf(r)===n}))}},185:e=>{"use strict";function t(e){return"function"==typeof e||Array.isArray(e)||"[object Object]"===Object.prototype.toString.call(e)}function r(e,n){if(e===n)return e;for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)&&"__proto__"!==i&&"constructor"!==i){var s=n[i],a=e[i];void 0!==a&&void 0===s||(t(a)&&t(s)?e[i]=r(a,s):e[i]="object"==typeof(c=s)&&null!==c?r(Array.isArray(c)?[]:{},c):c)}var c;return e}e.exports=function(e){t(e)||(e={});for(var n=1,i=arguments.length;n<i;n++){var s=arguments[n];t(s)&&r(e,s)}return e}},116:e=>{"use strict";e.exports=function(e){return e&&Object.keys(e).length>0}},9803:e=>{"use strict";e.exports=function(e,t){if(null===e)return{};var r,n,i={},s=Object.keys(e);for(n=0;n<s.length;n++)r=s[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}},2148:e=>{"use strict";function t(e,t){if(e!==t){var r=void 0!==e,n=null===e,i=void 0!==t,s=null===t;if(!s&&e>t||n&&i||!r)return 1;if(!n&&e<t||s&&r||!i)return-1}return 0}e.exports=function(e,r,n){if(!Array.isArray(e))return[];Array.isArray(n)||(n=[]);var i=e.map((function(e,t){return{criteria:r.map((function(t){return e[t]})),index:t,value:e}}));return i.sort((function(e,r){for(var i=-1;++i<e.criteria.length;){var s=t(e.criteria[i],r.criteria[i]);if(s)return i>=n.length?s:"desc"===n[i]?-s:s}return e.index-r.index})),i.map((function(e){return e.value}))}},8023:e=>{"use strict";e.exports=function e(t){if("number"==typeof t)return t;if("string"==typeof t)return parseFloat(t);if(Array.isArray(t))return t.map(e);throw new Error("The value should be a number, a parsable string or an array of those.")}},6394:(e,t,r)=>{"use strict";var n=r(185);function i(e){return Object.keys(e).sort().reduce((function(t,r){return t[r]=e[r],t}),{})}var s={_getQueries:function(e,t){var r=[];return r.push({indexName:e,params:s._getHitsSearchParams(t)}),t.getRefinedDisjunctiveFacets().forEach((function(n){r.push({indexName:e,params:s._getDisjunctiveFacetSearchParams(t,n)})})),t.getRefinedHierarchicalFacets().forEach((function(n){var i=t.getHierarchicalFacetByName(n),a=t.getHierarchicalRefinement(n),c=t._getHierarchicalFacetSeparator(i);if(a.length>0&&a[0].split(c).length>1){var u=a[0].split(c).slice(0,-1).reduce((function(e,t,r){return e.concat({attribute:i.attributes[r],value:0===r?t:[e[e.length-1].value,t].join(c)})}),[]);u.forEach((function(n,a){var c=s._getDisjunctiveFacetSearchParams(t,n.attribute,0===a);function o(e){return i.attributes.some((function(t){return t===e.split(":")[0]}))}var h=(c.facetFilters||[]).reduce((function(e,t){if(Array.isArray(t)){var r=t.filter((function(e){return!o(e)}));r.length>0&&e.push(r)}return"string"!=typeof t||o(t)||e.push(t),e}),[]),f=u[a-1];c.facetFilters=a>0?h.concat(f.attribute+":"+f.value):h.length>0?h:void 0,r.push({indexName:e,params:c})}))}})),r},_getHitsSearchParams:function(e){var t=e.facets.concat(e.disjunctiveFacets).concat(s._getHitsHierarchicalFacetsAttributes(e)).sort(),r=s._getFacetFilters(e),a=s._getNumericFilters(e),c=s._getTagFilters(e),u={facets:t.indexOf("*")>-1?["*"]:t,tagFilters:c};return r.length>0&&(u.facetFilters=r),a.length>0&&(u.numericFilters=a),i(n({},e.getQueryParams(),u))},_getDisjunctiveFacetSearchParams:function(e,t,r){var a=s._getFacetFilters(e,t,r),c=s._getNumericFilters(e,t),u=s._getTagFilters(e),o={hitsPerPage:0,page:0,analytics:!1,clickAnalytics:!1};u.length>0&&(o.tagFilters=u);var h=e.getHierarchicalFacetByName(t);return o.facets=h?s._getDisjunctiveHierarchicalFacetAttribute(e,h,r):t,c.length>0&&(o.numericFilters=c),a.length>0&&(o.facetFilters=a),i(n({},e.getQueryParams(),o))},_getNumericFilters:function(e,t){if(e.numericFilters)return e.numericFilters;var r=[];return Object.keys(e.numericRefinements).forEach((function(n){var i=e.numericRefinements[n]||{};Object.keys(i).forEach((function(e){var s=i[e]||[];t!==n&&s.forEach((function(t){if(Array.isArray(t)){var i=t.map((function(t){return n+e+t}));r.push(i)}else r.push(n+e+t)}))}))})),r},_getTagFilters:function(e){return e.tagFilters?e.tagFilters:e.tagRefinements.join(",")},_getFacetFilters:function(e,t,r){var n=[],i=e.facetsRefinements||{};Object.keys(i).sort().forEach((function(e){(i[e]||[]).sort().forEach((function(t){n.push(e+":"+t)}))}));var s=e.facetsExcludes||{};Object.keys(s).sort().forEach((function(e){(s[e]||[]).sort().forEach((function(t){n.push(e+":-"+t)}))}));var a=e.disjunctiveFacetsRefinements||{};Object.keys(a).sort().forEach((function(e){var r=a[e]||[];if(e!==t&&r&&0!==r.length){var i=[];r.sort().forEach((function(t){i.push(e+":"+t)})),n.push(i)}}));var c=e.hierarchicalFacetsRefinements||{};return Object.keys(c).sort().forEach((function(i){var s=(c[i]||[])[0];if(void 0!==s){var a,u,o=e.getHierarchicalFacetByName(i),h=e._getHierarchicalFacetSeparator(o),f=e._getHierarchicalRootPath(o);if(t===i){if(-1===s.indexOf(h)||!f&&!0===r||f&&f.split(h).length===s.split(h).length)return;f?(u=f.split(h).length-1,s=f):(u=s.split(h).length-2,s=s.slice(0,s.lastIndexOf(h))),a=o.attributes[u]}else u=s.split(h).length-1,a=o.attributes[u];a&&n.push([a+":"+s])}})),n},_getHitsHierarchicalFacetsAttributes:function(e){return e.hierarchicalFacets.reduce((function(t,r){var n=e.getHierarchicalRefinement(r.name)[0];if(!n)return t.push(r.attributes[0]),t;var i=e._getHierarchicalFacetSeparator(r),s=n.split(i).length,a=r.attributes.slice(0,s+1);return t.concat(a)}),[])},_getDisjunctiveHierarchicalFacetAttribute:function(e,t,r){var n=e._getHierarchicalFacetSeparator(t);if(!0===r){var i=e._getHierarchicalRootPath(t),s=0;return i&&(s=i.split(n).length),[t.attributes[s]]}var a=(e.getHierarchicalRefinement(t.name)[0]||"").split(n).length-1;return t.attributes.slice(0,a+1)},getSearchForFacetQuery:function(e,t,r,a){var c=a.isDisjunctiveFacet(e)?a.clearRefinements(e):a,u={facetQuery:t,facetName:e};return"number"==typeof r&&(u.maxFacetHits=r),i(n({},s._getHitsSearchParams(c),u))}};e.exports=s},6801:e=>{"use strict";e.exports=function(e){return null!==e&&/^[a-zA-Z0-9_-]{1,64}$/.test(e)}},4336:e=>{"use strict";e.exports="3.16.1"},290:function(e){e.exports=function(){"use strict";function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function r(r){for(var n=1;n<arguments.length;n++){var i=null!=arguments[n]?arguments[n]:{};n%2?t(Object(i),!0).forEach((function(t){e(r,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(i)):t(Object(i)).forEach((function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(i,e))}))}return r}function n(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},s=Object.keys(e);for(n=0;n<s.length;n++)r=s[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n<s.length;n++)r=s[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],n=!0,i=!1,s=void 0;try{for(var a,c=e[Symbol.iterator]();!(n=(a=c.next()).done)&&(r.push(a.value),!t||r.length!==t);n=!0);}catch(e){i=!0,s=e}finally{try{n||null==c.return||c.return()}finally{if(i)throw s}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function s(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t<e.length;t++)r[t]=e[t];return r}}(e)||function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function a(e){var t,r="algoliasearch-client-js-".concat(e.key),n=function(){return void 0===t&&(t=e.localStorage||window.localStorage),t},s=function(){return JSON.parse(n().getItem(r)||"{}")},a=function(e){n().setItem(r,JSON.stringify(e))},c=function(){var t=e.timeToLive?1e3*e.timeToLive:null,r=s(),n=Object.fromEntries(Object.entries(r).filter((function(e){return void 0!==i(e,2)[1].timestamp})));if(a(n),t){var c=Object.fromEntries(Object.entries(n).filter((function(e){var r=i(e,2)[1],n=(new Date).getTime();return!(r.timestamp+t<n)})));a(c)}};return{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){c();var t=JSON.stringify(e);return s()[t]})).then((function(e){return Promise.all([e?e.value:t(),void 0!==e])})).then((function(e){var t=i(e,2),n=t[0],s=t[1];return Promise.all([n,s||r.miss(n)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var i=s();return i[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:t},n().setItem(r,JSON.stringify(i)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=s();delete t[JSON.stringify(e)],n().setItem(r,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){n().removeItem(r)}))}}}function c(e){var t=s(e.caches),r=t.shift();return void 0===r?{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return t().then((function(e){return Promise.all([e,r.miss(e)])})).then((function(e){return i(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return r.get(e,n,i).catch((function(){return c({caches:t}).get(e,n,i)}))},set:function(e,n){return r.set(e,n).catch((function(){return c({caches:t}).set(e,n)}))},delete:function(e){return r.delete(e).catch((function(){return c({caches:t}).delete(e)}))},clear:function(){return r.clear().catch((function(){return c({caches:t}).clear()}))}}}function u(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(r,n){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},s=JSON.stringify(r);if(s in t)return Promise.resolve(e.serializable?JSON.parse(t[s]):t[s]);var a=n(),c=i&&i.miss||function(){return Promise.resolve()};return a.then((function(e){return c(e)})).then((function(){return a}))},set:function(r,n){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function o(e){for(var t=e.length-1;t>0;t--){var r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function h(e,t){return t?(Object.keys(t).forEach((function(r){e[r]=t[r](e)})),e):e}function f(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];var i=0;return e.replace(/%s/g,(function(){return encodeURIComponent(r[i++])}))}var l={WithinQueryParameters:0,WithinHeaders:1};function m(e,t){var r=e||{},n=r.data||{};return Object.keys(r).forEach((function(e){-1===["timeout","headers","queryParameters","data","cacheable"].indexOf(e)&&(n[e]=r[e])})),{data:Object.entries(n).length>0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var d={Read:1,Write:2,Any:3},p=1,v=2,g=3;function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:p;return r(r({},e),{},{status:t,lastUpdate:Date.now()})}function R(e){return"string"==typeof e?{protocol:"https",url:e,accept:d.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||d.Any}}var F="GET",b="POST";function j(e,t){return Promise.all(t.map((function(t){return e.get(t,(function(){return Promise.resolve(y(t))}))}))).then((function(e){var r=e.filter((function(e){return function(e){return e.status===p||Date.now()-e.lastUpdate>12e4}(e)})),n=e.filter((function(e){return function(e){return e.status===g&&Date.now()-e.lastUpdate<=12e4}(e)})),i=[].concat(s(r),s(n));return{getTimeout:function(e,t){return(0===n.length&&0===e?1:n.length+3+e)*t},statelessHosts:i.length>0?i.map((function(e){return R(e)})):t}}))}function P(e,t,n,i){var a=[],c=function(e,t){if(e.method!==F&&(void 0!==e.data||void 0!==t.data)){var n=Array.isArray(e.data)?e.data:r(r({},e.data),t.data);return JSON.stringify(n)}}(n,i),u=function(e,t){var n=r(r({},e.headers),t.headers),i={};return Object.keys(n).forEach((function(e){var t=n[e];i[e.toLowerCase()]=t})),i}(e,i),o=n.method,h=n.method!==F?{}:r(r({},n.data),i.data),f=r(r(r({"x-algolia-agent":e.userAgent.value},e.queryParameters),h),i.queryParameters),l=0,m=function t(r,s){var h=r.pop();if(void 0===h)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:O(a)};var m={data:c,headers:u,method:o,url:_(h,n.path,f),connectTimeout:s(l,e.timeouts.connect),responseTimeout:s(l,i.timeout)},d=function(e){var t={request:m,response:e,host:h,triesLeft:r.length};return a.push(t),t},p={onSuccess:function(e){return function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e)},onRetry:function(n){var i=d(n);return n.isTimedOut&&l++,Promise.all([e.logger.info("Retryable failure",w(i)),e.hostsCache.set(h,y(h,n.isTimedOut?g:v))]).then((function(){return t(r,s)}))},onFail:function(e){throw d(e),function(e,t){var r=e.content,n=e.status,i=r;try{i=JSON.parse(r).message}catch(e){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(i,n,t)}(e,O(a))}};return e.requester.send(m).then((function(e){return function(e,t){return function(e){var t=e.status;return e.isTimedOut||function(e){var t=e.isTimedOut,r=e.status;return!t&&0==~~r}(e)||2!=~~(t/100)&&4!=~~(t/100)}(e)?t.onRetry(e):2==~~(e.status/100)?t.onSuccess(e):t.onFail(e)}(e,p)}))};return j(e.hostsCache,t).then((function(e){return m(s(e.statelessHosts).reverse(),e.getTimeout)}))}function x(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var r="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(r)&&(t.value="".concat(t.value).concat(r)),t}};return t}function _(e,t,r){var n=E(r),i="".concat(e.protocol,"://").concat(e.url,"/").concat("/"===t.charAt(0)?t.substr(1):t);return n.length&&(i+="?".concat(n)),i}function E(e){return Object.keys(e).map((function(t){return f("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function O(e){return e.map((function(e){return w(e)}))}function w(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return r(r({},e),{},{request:r(r({},e.request),{},{headers:r(r({},e.request.headers),t)})})}var N=function(e){var t=e.appId,n=function(e,t,r){var n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:function(){return e===l.WithinHeaders?n:{}},queryParameters:function(){return e===l.WithinQueryParameters?n:{}}}}(void 0!==e.authMode?e.authMode:l.WithinHeaders,t,e.apiKey),s=function(e){var t=e.hostsCache,r=e.logger,n=e.requester,s=e.requestsCache,a=e.responsesCache,c=e.timeouts,u=e.userAgent,o=e.hosts,h=e.queryParameters,f={hostsCache:t,logger:r,requester:n,requestsCache:s,responsesCache:a,timeouts:c,userAgent:u,headers:e.headers,queryParameters:h,hosts:o.map((function(e){return R(e)})),read:function(e,t){var r=m(t,f.timeouts.read),n=function(){return P(f,f.hosts.filter((function(e){return 0!=(e.accept&d.Read)})),e,r)};if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();var s={request:e,mappedRequestOptions:r,transporter:{queryParameters:f.queryParameters,headers:f.headers}};return f.responsesCache.get(s,(function(){return f.requestsCache.get(s,(function(){return f.requestsCache.set(s,n()).then((function(e){return Promise.all([f.requestsCache.delete(s),e])}),(function(e){return Promise.all([f.requestsCache.delete(s),Promise.reject(e)])})).then((function(e){var t=i(e,2);return t[0],t[1]}))}))}),{miss:function(e){return f.responsesCache.set(s,e)}})},write:function(e,t){return P(f,f.hosts.filter((function(e){return 0!=(e.accept&d.Write)})),e,m(t,f.timeouts.write))}};return f}(r(r({hosts:[{url:"".concat(t,"-dsn.algolia.net"),accept:d.Read},{url:"".concat(t,".algolia.net"),accept:d.Write}].concat(o([{url:"".concat(t,"-1.algolianet.com")},{url:"".concat(t,"-2.algolianet.com")},{url:"".concat(t,"-3.algolianet.com")}]))},e),{},{headers:r(r(r({},n.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:r(r({},n.queryParameters()),e.queryParameters)}));return h({transporter:s,appId:t,addAlgoliaAgent:function(e,t){s.userAgent.add({segment:e,version:t})},clearCache:function(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then((function(){}))}},e.methods)},A=function(e){return function(t,r){return t.method===F?e.transporter.read(t,r):e.transporter.write(t,r)}},H=function(e){return function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return h({transporter:e.transporter,appId:e.appId,indexName:t},r.methods)}},S=function(e){return function(t,n){var i=t.map((function(e){return r(r({},e),{},{params:E(e.params||{})})}));return e.transporter.read({method:b,path:"1/indexes/*/queries",data:{requests:i},cacheable:!0},n)}},T=function(e){return function(t,i){return Promise.all(t.map((function(t){var s=t.params,a=s.facetName,c=s.facetQuery,u=n(s,["facetName","facetQuery"]);return H(e)(t.indexName,{methods:{searchForFacetValues:I}}).searchForFacetValues(a,c,r(r({},i),u))})))}},Q=function(e){return function(t,r,n){return e.transporter.read({method:b,path:f("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},n)}},C=function(e){return function(t,r){return e.transporter.read({method:b,path:f("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r)}},I=function(e){return function(t,r,n){return e.transporter.read({method:b,path:f("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n)}},D=1,k=2,q=3;function V(e,t,n){var i,s={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:function(e){return new Promise((function(t){var r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return r.setRequestHeader(t,e.headers[t])}));var n,i=function(e,n){return setTimeout((function(){r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e)},s=i(e.connectTimeout,"Connection timeout");r.onreadystatechange=function(){r.readyState>r.OPENED&&void 0===n&&(clearTimeout(s),n=i(e.responseTimeout,"Socket timeout"))},r.onerror=function(){0===r.status&&(clearTimeout(s),clearTimeout(n),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=function(){clearTimeout(s),clearTimeout(n),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))}},logger:(i=q,{debug:function(e,t){return D>=i&&console.debug(e,t),Promise.resolve()},info:function(e,t){return k>=i&&console.info(e,t),Promise.resolve()},error:function(e,t){return console.error(e,t),Promise.resolve()}}),responsesCache:u(),requestsCache:u({serializable:!1}),hostsCache:c({caches:[a({key:"".concat("4.22.1","-").concat(e)}),u()]}),userAgent:x("4.22.1").add({segment:"Browser",version:"lite"}),authMode:l.WithinQueryParameters};return N(r(r(r({},s),n),{},{methods:{search:S,searchForFacetValues:T,multipleQueries:S,multipleSearchForFacetValues:T,customRequest:A,initIndex:function(e){return function(t){return H(e)(t,{methods:{search:C,searchForFacetValues:I,findAnswers:Q}})}}}}))}return V.version="4.22.1",V}()},6675:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>S});var n=r(7294),i=r(512),s=r(8131),a=r.n(s),c=r(290),u=r.n(c),o=r(412),h=r(5742),f=r(3692),l=r(143),m=r(2263);const d=["zero","one","two","few","many","other"];function p(e){return d.filter((t=>e.includes(t)))}const v={locale:"en",pluralForms:p(["one","other"]),select:e=>1===e?"one":"other"};function g(){const{i18n:{currentLocale:e}}=(0,m.Z)();return(0,n.useMemo)((()=>{try{return function(e){const t=new Intl.PluralRules(e);return{locale:e,pluralForms:p(t.resolvedOptions().pluralCategories),select:e=>t.select(e)}}(e)}catch(t){return console.error(`Failed to use Intl.PluralRules for locale "${e}".\nDocusaurus will fallback to the default (English) implementation.\nError: ${t.message}\n`),v}}),[e])}function y(){const e=g();return{selectMessage:(t,r)=>function(e,t,r){const n=e.split("|");if(1===n.length)return n[0];n.length>r.pluralForms.length&&console.error(`For locale=${r.locale}, a maximum of ${r.pluralForms.length} plural forms are expected (${r.pluralForms.join(",")}), but the message contains ${n.length}: ${e}`);const i=r.select(t),s=r.pluralForms.indexOf(i);return n[Math.min(s,n.length-1)]}(r,t,e)}}var R=r(6177),F=r(902),b=r(833),j=r(2128),P=r(5999),x=r(6278),_=r(239),E=r(7372),O=r(2503);const w={searchQueryInput:"searchQueryInput_u2C7",searchVersionInput:"searchVersionInput_m0Ui",searchResultsColumn:"searchResultsColumn_JPFH",algoliaLogo:"algoliaLogo_rT1R",algoliaLogoPathFill:"algoliaLogoPathFill_WdUC",searchResultItem:"searchResultItem_Tv2o",searchResultItemHeading:"searchResultItemHeading_KbCB",searchResultItemPath:"searchResultItemPath_lhe1",searchResultItemSummary:"searchResultItemSummary_AEaO",searchQueryColumn:"searchQueryColumn_RTkw",searchVersionColumn:"searchVersionColumn_ypXd",searchLogoColumn:"searchLogoColumn_rJIA",loadingSpinner:"loadingSpinner_XVxU","loading-spin":"loading-spin_vzvp",loader:"loader_vvXV"};var N=r(5893);function A(e){let{docsSearchVersionsHelpers:t}=e;const r=Object.entries(t.allDocsData).filter((e=>{let[,t]=e;return t.versions.length>1}));return(0,N.jsx)("div",{className:(0,i.Z)("col","col--3","padding-left--none",w.searchVersionColumn),children:r.map((e=>{let[n,i]=e;const s=r.length>1?`${n}: `:"";return(0,N.jsx)("select",{onChange:e=>t.setSearchVersion(n,e.target.value),defaultValue:t.searchVersions[n],className:w.searchVersionInput,children:i.versions.map(((e,t)=>(0,N.jsx)("option",{label:`${s}${e.label}`,value:e.name},t)))},n)}))})}function H(){const{i18n:{currentLocale:e}}=(0,m.Z)(),{algolia:{appId:t,apiKey:r,indexName:s}}=(0,x.L)(),c=(0,_.l)(),d=function(){const{selectMessage:e}=y();return t=>e(t,(0,P.I)({id:"theme.SearchPage.documentsFound.plurals",description:'Pluralized label for "{count} documents found". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',message:"One document found|{count} documents found"},{count:t}))}(),p=function(){const e=(0,l._r)(),[t,r]=(0,n.useState)((()=>Object.entries(e).reduce(((e,t)=>{let[r,n]=t;return{...e,[r]:n.versions[0].name}}),{}))),i=Object.values(e).some((e=>e.versions.length>1));return{allDocsData:e,versioningEnabled:i,searchVersions:t,setSearchVersion:(e,t)=>r((r=>({...r,[e]:t})))}}(),[v,g]=(0,R.K)(),b={items:[],query:null,totalResults:null,totalPages:null,lastPage:null,hasMore:null,loading:null},[H,S]=(0,n.useReducer)(((e,t)=>{switch(t.type){case"reset":return b;case"loading":return{...e,loading:!0};case"update":return v!==t.value.query?e:{...t.value,items:0===t.value.lastPage?t.value.items:e.items.concat(t.value.items)};case"advance":{const t=e.totalPages>e.lastPage+1;return{...e,lastPage:t?e.lastPage+1:e.lastPage,hasMore:t}}default:return e}}),b),T=u()(t,r),Q=a()(T,s,{hitsPerPage:15,advancedSyntax:!0,disjunctiveFacets:["language","docusaurus_tag"]});Q.on("result",(e=>{let{results:{query:t,hits:r,page:n,nbHits:i,nbPages:s}}=e;if(""===t||!Array.isArray(r))return void S({type:"reset"});const a=e=>e.replace(/algolia-docsearch-suggestion--highlight/g,"search-result-match"),u=r.map((e=>{let{url:t,_highlightResult:{hierarchy:r},_snippetResult:n={}}=e;const i=Object.keys(r).map((e=>a(r[e].value)));return{title:i.pop(),url:c(t),summary:n.content?`${a(n.content.value)}...`:"",breadcrumbs:i}}));S({type:"update",value:{items:u,query:t,totalResults:i,totalPages:s,lastPage:n,hasMore:s>n+1,loading:!1}})}));const[C,I]=(0,n.useState)(null),D=(0,n.useRef)(0),k=(0,n.useRef)(o.Z.canUseIntersectionObserver&&new IntersectionObserver((e=>{const{isIntersecting:t,boundingClientRect:{y:r}}=e[0];t&&D.current>r&&S({type:"advance"}),D.current=r}),{threshold:1})),q=()=>v?(0,P.I)({id:"theme.SearchPage.existingResultsTitle",message:'Search results for "{query}"',description:"The search page title for non-empty query"},{query:v}):(0,P.I)({id:"theme.SearchPage.emptyResultsTitle",message:"Search the documentation",description:"The search page title for empty query"}),V=(0,F.zX)((function(t){void 0===t&&(t=0),Q.addDisjunctiveFacetRefinement("docusaurus_tag","default"),Q.addDisjunctiveFacetRefinement("language",e),Object.entries(p.searchVersions).forEach((e=>{let[t,r]=e;Q.addDisjunctiveFacetRefinement("docusaurus_tag",`docs-${t}-${r}`)})),Q.setQuery(v).setPage(t).search()}));return(0,n.useEffect)((()=>{if(!C)return;const e=k.current;return e?(e.observe(C),()=>e.unobserve(C)):()=>!0}),[C]),(0,n.useEffect)((()=>{S({type:"reset"}),v&&(S({type:"loading"}),setTimeout((()=>{V()}),300))}),[v,p.searchVersions,V]),(0,n.useEffect)((()=>{H.lastPage&&0!==H.lastPage&&V(H.lastPage)}),[V,H.lastPage]),(0,N.jsxs)(E.Z,{children:[(0,N.jsxs)(h.Z,{children:[(0,N.jsx)("title",{children:(0,j.p)(q())}),(0,N.jsx)("meta",{property:"robots",content:"noindex, follow"})]}),(0,N.jsxs)("div",{className:"container margin-vert--lg",children:[(0,N.jsx)(O.Z,{as:"h1",children:q()}),(0,N.jsxs)("form",{className:"row",onSubmit:e=>e.preventDefault(),children:[(0,N.jsx)("div",{className:(0,i.Z)("col",w.searchQueryColumn,{"col--9":p.versioningEnabled,"col--12":!p.versioningEnabled}),children:(0,N.jsx)("input",{type:"search",name:"q",className:w.searchQueryInput,placeholder:(0,P.I)({id:"theme.SearchPage.inputPlaceholder",message:"Type your search here",description:"The placeholder for search page input"}),"aria-label":(0,P.I)({id:"theme.SearchPage.inputLabel",message:"Search",description:"The ARIA label for search page input"}),onChange:e=>g(e.target.value),value:v,autoComplete:"off",autoFocus:!0})}),p.versioningEnabled&&(0,N.jsx)(A,{docsSearchVersionsHelpers:p})]}),(0,N.jsxs)("div",{className:"row",children:[(0,N.jsx)("div",{className:(0,i.Z)("col","col--8",w.searchResultsColumn),children:!!H.totalResults&&d(H.totalResults)}),(0,N.jsx)("div",{className:(0,i.Z)("col","col--4","text--right",w.searchLogoColumn),children:(0,N.jsx)(f.Z,{to:"https://www.algolia.com/","aria-label":(0,P.I)({id:"theme.SearchPage.algoliaLabel",message:"Search by Algolia",description:"The ARIA label for Algolia mention"}),children:(0,N.jsx)("svg",{viewBox:"0 0 168 24",className:w.algoliaLogo,children:(0,N.jsxs)("g",{fill:"none",children:[(0,N.jsx)("path",{className:w.algoliaLogoPathFill,d:"M120.925 18.804c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17zM6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z"}),(0,N.jsx)("path",{fill:"#5468FF",d:"M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938z"}),(0,N.jsx)("path",{fill:"white",d:"M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36"})]})})})})]}),H.items.length>0?(0,N.jsx)("main",{children:H.items.map(((e,t)=>{let{title:r,url:n,summary:s,breadcrumbs:a}=e;return(0,N.jsxs)("article",{className:w.searchResultItem,children:[(0,N.jsx)(O.Z,{as:"h2",className:w.searchResultItemHeading,children:(0,N.jsx)(f.Z,{to:n,dangerouslySetInnerHTML:{__html:r}})}),a.length>0&&(0,N.jsx)("nav",{"aria-label":"breadcrumbs",children:(0,N.jsx)("ul",{className:(0,i.Z)("breadcrumbs",w.searchResultItemPath),children:a.map(((e,t)=>(0,N.jsx)("li",{className:"breadcrumbs__item",dangerouslySetInnerHTML:{__html:e}},t)))})}),s&&(0,N.jsx)("p",{className:w.searchResultItemSummary,dangerouslySetInnerHTML:{__html:s}})]},t)}))}):[v&&!H.loading&&(0,N.jsx)("p",{children:(0,N.jsx)(P.Z,{id:"theme.SearchPage.noResultsText",description:"The paragraph for empty search result",children:"No results were found"})},"no-results"),!!H.loading&&(0,N.jsx)("div",{className:w.loadingSpinner},"spinner")],H.hasMore&&(0,N.jsx)("div",{className:w.loader,ref:I,children:(0,N.jsx)(P.Z,{id:"theme.SearchPage.fetchingNewResults",description:"The paragraph for fetching new search results",children:"Fetching new results..."})})]})]})}function S(){return(0,N.jsx)(b.FG,{className:"search-page-wrapper",children:(0,N.jsx)(H,{})})}}}]); \ No newline at end of file diff --git a/docs/assets/js/1a4e3797.cdef43d5.js.LICENSE.txt b/docs/assets/js/1a4e3797.cdef43d5.js.LICENSE.txt new file mode 100644 index 0000000000..9caab8b19c --- /dev/null +++ b/docs/assets/js/1a4e3797.cdef43d5.js.LICENSE.txt @@ -0,0 +1 @@ +/*! algoliasearch-lite.umd.js | 4.22.1 | © Algolia, inc. | https://github.com/algolia/algoliasearch-client-javascript */ diff --git a/docs/assets/js/1b064146.869a4cad.js b/docs/assets/js/1b064146.869a4cad.js new file mode 100644 index 0000000000..f0bec17024 --- /dev/null +++ b/docs/assets/js/1b064146.869a4cad.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4178],{8368:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var r=n(5893),t=n(1151);const a={},i="Release Management",l={id:"release-management",title:"Release Management",description:"Overview",source:"@site/docs/release-management.md",sourceDirName:".",slug:"/release-management",permalink:"/eraser/docs/next/release-management",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{}},o={},c=[{value:"Overview",id:"overview",level:2},{value:"Legend",id:"legend",level:2},{value:"Release Versioning",id:"release-versioning",level:2},{value:"Supported Releases",id:"supported-releases",level:2},{value:"Supported Kubernetes Versions",id:"supported-kubernetes-versions",level:2},{value:"Acknowledgement",id:"acknowledgement",level:2}];function d(e){const s={a:"a",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h1,{id:"release-management",children:"Release Management"}),"\n",(0,r.jsx)(s.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(s.p,{children:"This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades."}),"\n",(0,r.jsx)(s.h2,{id:"legend",children:"Legend"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"X.Y.Z"})," refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Breaking changes"})," refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Milestone"})," should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Patch releases"})," refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Test gates"})," should include soak tests and upgrade tests from the last minor version."]}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"release-versioning",children:"Release Versioning"}),"\n",(0,r.jsxs)(s.p,{children:["All releases will be of the form ",(0,r.jsx)(s.em,{children:"vX.Y.Z"})," where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning."]}),"\n",(0,r.jsx)(s.p,{children:"The rest of the doc will cover the release process for the following kinds of releases:"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Major Releases"})}),"\n",(0,r.jsx)(s.p,{children:"No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Minor Releases"})}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["X.Y.0-alpha.W, W >= 0 (Branch : main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released as needed before we cut a beta X.Y release"}),"\n",(0,r.jsx)(s.li,{children:"Alpha release, cut from master branch"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.li,{children:["X.Y.0-beta.W, W >= 0 (Branch : main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released as needed before we cut a stable X.Y release"}),"\n",(0,r.jsx)(s.li,{children:"More stable than the alpha release to signal users to test things out"}),"\n",(0,r.jsx)(s.li,{children:"Beta release, cut from master branch"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.li,{children:["X.Y.0-rc.W, W >= 0 (Branch : main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released as needed before we cut a stable X.Y release"}),"\n",(0,r.jsx)(s.li,{children:"soak for ~ 2 weeks before cutting a stable release"}),"\n",(0,r.jsx)(s.li,{children:"Release candidate release, cut from master branch"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.li,{children:["X.Y.0 (Branch: main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released every ~ 3 months"}),"\n",(0,r.jsx)(s.li,{children:"Stable release, cut from master when X.Y milestone is complete"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Patch Releases"})}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No breaking changes"}),"\n",(0,r.jsx)(s.li,{children:"Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches."}),"\n",(0,r.jsx)(s.li,{children:"Patch release, cut from a release-X.Y branch"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"supported-releases",children:"Supported Releases"}),"\n",(0,r.jsx)(s.p,{children:"Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed."}),"\n",(0,r.jsx)(s.p,{children:"We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible."}),"\n",(0,r.jsx)(s.p,{children:'We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.'}),"\n",(0,r.jsx)(s.h2,{id:"supported-kubernetes-versions",children:"Supported Kubernetes Versions"}),"\n",(0,r.jsxs)(s.p,{children:["Eraser is assumed to be compatible with the ",(0,r.jsx)(s.a,{href:"https://kubernetes.io/releases/patch-releases/#detailed-release-history-for-active-branches",children:"current Kubernetes Supported Versions"})," per ",(0,r.jsx)(s.a,{href:"https://kubernetes.io/releases/version-skew-policy/",children:"Kubernetes Supported Versions policy"}),"."]}),"\n",(0,r.jsxs)(s.p,{children:["For example, if Eraser ",(0,r.jsx)(s.em,{children:"supported"})," versions are v1.2 and v1.1, and Kubernetes ",(0,r.jsx)(s.em,{children:"supported"})," versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time."]}),"\n",(0,r.jsx)(s.p,{children:"If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk."}),"\n",(0,r.jsx)(s.h2,{id:"acknowledgement",children:"Acknowledgement"}),"\n",(0,r.jsx)(s.p,{children:"This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm."})]})}function h(e={}){const{wrapper:s}={...(0,t.a)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,s,n)=>{n.d(s,{Z:()=>l,a:()=>i});var r=n(7294);const t={},a=r.createContext(t);function i(e){const s=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),r.createElement(a.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/1b064146.b78fd6fa.js b/docs/assets/js/1b064146.b78fd6fa.js deleted file mode 100644 index 384c0cb4c7..0000000000 --- a/docs/assets/js/1b064146.b78fd6fa.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4178],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var a=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?s(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):s(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,a,n=function(e,t){if(null==e)return{};var r,a,n={},s=Object.keys(e);for(a=0;a<s.length;a++)r=s[a],t.indexOf(r)>=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a<s.length;a++)r=s[a],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var i=a.createContext({}),p=function(e){var t=a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=p(e.components);return a.createElement(i.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,s=e.originalType,i=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),m=p(r),d=n,h=m["".concat(i,".").concat(d)]||m[d]||c[d]||s;return r?a.createElement(h,l(l({ref:t},u),{},{components:r})):a.createElement(h,l({ref:t},u))}));function d(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var s=r.length,l=new Array(s);l[0]=m;var o={};for(var i in t)hasOwnProperty.call(t,i)&&(o[i]=t[i]);o.originalType=e,o.mdxType="string"==typeof e?e:n,l[1]=o;for(var p=2;p<s;p++)l[p]=r[p];return a.createElement.apply(null,l)}return a.createElement.apply(null,r)}m.displayName="MDXCreateElement"},3648:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>c,frontMatter:()=>s,metadata:()=>o,toc:()=>p});var a=r(7462),n=(r(7294),r(3905));const s={},l="Release Management",o={unversionedId:"release-management",id:"release-management",title:"Release Management",description:"Overview",source:"@site/docs/release-management.md",sourceDirName:".",slug:"/release-management",permalink:"/eraser/docs/next/release-management",draft:!1,tags:[],version:"current",frontMatter:{}},i={},p=[{value:"Overview",id:"overview",level:2},{value:"Legend",id:"legend",level:2},{value:"Release Versioning",id:"release-versioning",level:2},{value:"Supported Releases",id:"supported-releases",level:2},{value:"Supported Kubernetes Versions",id:"supported-kubernetes-versions",level:2},{value:"Acknowledgement",id:"acknowledgement",level:2}],u={toc:p};function c(e){let{components:t,...r}=e;return(0,n.kt)("wrapper",(0,a.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"release-management"},"Release Management"),(0,n.kt)("h2",{id:"overview"},"Overview"),(0,n.kt)("p",null,"This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades."),(0,n.kt)("h2",{id:"legend"},"Legend"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"X.Y.Z")," refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Breaking changes")," refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Milestone")," should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Patch releases")," refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Test gates")," should include soak tests and upgrade tests from the last minor version.")),(0,n.kt)("h2",{id:"release-versioning"},"Release Versioning"),(0,n.kt)("p",null,"All releases will be of the form ",(0,n.kt)("em",{parentName:"p"},"vX.Y.Z")," where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning."),(0,n.kt)("p",null,"The rest of the doc will cover the release process for the following kinds of releases:"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Major Releases")),(0,n.kt)("p",null,"No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Minor Releases")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"X.Y.0-alpha.W, W >= 0 (Branch : main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released as needed before we cut a beta X.Y release"),(0,n.kt)("li",{parentName:"ul"},"Alpha release, cut from master branch"))),(0,n.kt)("li",{parentName:"ul"},"X.Y.0-beta.W, W >= 0 (Branch : main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released as needed before we cut a stable X.Y release"),(0,n.kt)("li",{parentName:"ul"},"More stable than the alpha release to signal users to test things out"),(0,n.kt)("li",{parentName:"ul"},"Beta release, cut from master branch"))),(0,n.kt)("li",{parentName:"ul"},"X.Y.0-rc.W, W >= 0 (Branch : main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released as needed before we cut a stable X.Y release"),(0,n.kt)("li",{parentName:"ul"},"soak for ~ 2 weeks before cutting a stable release"),(0,n.kt)("li",{parentName:"ul"},"Release candidate release, cut from master branch"))),(0,n.kt)("li",{parentName:"ul"},"X.Y.0 (Branch: main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released every ~ 3 months"),(0,n.kt)("li",{parentName:"ul"},"Stable release, cut from master when X.Y milestone is complete")))),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Patch Releases")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"No breaking changes"),(0,n.kt)("li",{parentName:"ul"},"Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches."),(0,n.kt)("li",{parentName:"ul"},"Patch release, cut from a release-X.Y branch")))),(0,n.kt)("h2",{id:"supported-releases"},"Supported Releases"),(0,n.kt)("p",null,"Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed."),(0,n.kt)("p",null,"We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible."),(0,n.kt)("p",null,'We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.'),(0,n.kt)("h2",{id:"supported-kubernetes-versions"},"Supported Kubernetes Versions"),(0,n.kt)("p",null,"Eraser is assumed to be compatible with the ",(0,n.kt)("a",{parentName:"p",href:"https://kubernetes.io/releases/patch-releases/#detailed-release-history-for-active-branches"},"current Kubernetes Supported Versions")," per ",(0,n.kt)("a",{parentName:"p",href:"https://kubernetes.io/releases/version-skew-policy/"},"Kubernetes Supported Versions policy"),"."),(0,n.kt)("p",null,"For example, if Eraser ",(0,n.kt)("em",{parentName:"p"},"supported")," versions are v1.2 and v1.1, and Kubernetes ",(0,n.kt)("em",{parentName:"p"},"supported")," versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time."),(0,n.kt)("p",null,"If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk."),(0,n.kt)("h2",{id:"acknowledgement"},"Acknowledgement"),(0,n.kt)("p",null,"This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/1be78505.f8b40e6f.js b/docs/assets/js/1be78505.f8b40e6f.js deleted file mode 100644 index 0c332a8ece..0000000000 --- a/docs/assets/js/1be78505.f8b40e6f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9514,4972],{9963:(e,t,n)=>{n.r(t),n.d(t,{default:()=>Se});var a=n(7294),l=n(4334),o=n(833),r=n(5281),i=n(3320),c=n(2802),s=n(4477),d=n(1116),m=n(7452),u=n(5999),b=n(2466),p=n(5936);const h="backToTopButton_sjWU",E="backToTopButtonShow_xfvO";function f(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,l]=(0,a.useState)(!1),o=(0,a.useRef)(!1),{startScroll:r,cancelScroll:i}=(0,b.Ct)();return(0,b.RF)(((e,n)=>{let{scrollY:a}=e;const r=null==n?void 0:n.scrollY;r&&(o.current?o.current=!1:a>=r?(i(),l(!1)):a<t?l(!1):a+window.innerHeight<document.documentElement.scrollHeight&&l(!0))})),(0,p.S)((e=>{e.location.hash&&(o.current=!0,l(!1))})),{shown:n,scrollToTop:()=>r(0)}}({threshold:300});return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,l.Z)("clean-btn",r.k.common.backToTopButton,h,e&&E),type:"button",onClick:t})}var v=n(1442),g=n(6775),_=n(7524),k=n(6668),C=n(1327),S=n(7462);function I(e){return a.createElement("svg",(0,S.Z)({width:"20",height:"20","aria-hidden":"true"},e),a.createElement("g",{fill:"#7a7a7a"},a.createElement("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),a.createElement("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})))}const N="collapseSidebarButton_PEFL",Z="collapseSidebarButtonIcon_kv0_";function x(e){let{onClick:t}=e;return a.createElement("button",{type:"button",title:(0,u.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,l.Z)("button button--secondary button--outline",N),onClick:t},a.createElement(I,{className:Z}))}var T=n(9689),y=n(902);const w=Symbol("EmptyContext"),L=a.createContext(w);function A(e){let{children:t}=e;const[n,l]=(0,a.useState)(null),o=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:l})),[n]);return a.createElement(L.Provider,{value:o},t)}var M=n(6043),B=n(8596),F=n(9960),H=n(2389);function P(e){let{categoryLabel:t,onClick:n}=e;return a.createElement("button",{"aria-label":(0,u.I)({id:"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel",message:"Toggle the collapsible sidebar category '{label}'",description:"The ARIA label to toggle the collapsible sidebar category"},{label:t}),type:"button",className:"clean-btn menu__caret",onClick:n})}function D(e){let{item:t,onItemClick:n,activePath:o,level:i,index:s,...d}=e;const{items:m,label:u,collapsible:b,className:p,href:h}=t,{docs:{sidebar:{autoCollapseCategories:E}}}=(0,k.L)(),f=function(e){const t=(0,H.Z)();return(0,a.useMemo)((()=>e.href?e.href:!t&&e.collapsible?(0,c.Wl)(e):void 0),[e,t])}(t),v=(0,c._F)(t,o),g=(0,B.Mg)(h,o),{collapsed:_,setCollapsed:C}=(0,M.u)({initialState:()=>!!b&&(!v&&t.collapsed)}),{expandedItem:I,setExpandedItem:N}=function(){const e=(0,a.useContext)(L);if(e===w)throw new y.i6("DocSidebarItemsExpandedStateProvider");return e}(),Z=function(e){void 0===e&&(e=!_),N(e?null:s),C(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:l}=e;const o=(0,y.D9)(t);(0,a.useEffect)((()=>{t&&!o&&n&&l(!1)}),[t,o,n,l])}({isActive:v,collapsed:_,updateCollapsed:Z}),(0,a.useEffect)((()=>{b&&null!=I&&I!==s&&E&&C(!0)}),[b,I,s,C,E]),a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemCategory,r.k.docs.docSidebarItemCategoryLevel(i),"menu__list-item",{"menu__list-item--collapsed":_},p)},a.createElement("div",{className:(0,l.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":g})},a.createElement(F.Z,(0,S.Z)({className:(0,l.Z)("menu__link",{"menu__link--sublist":b,"menu__link--sublist-caret":!h&&b,"menu__link--active":v}),onClick:b?e=>{null==n||n(t),h?Z(!1):(e.preventDefault(),Z())}:()=>{null==n||n(t)},"aria-current":g?"page":void 0,"aria-expanded":b?!_:void 0,href:b?null!=f?f:"#":f},d),u),h&&b&&a.createElement(P,{categoryLabel:u,onClick:e=>{e.preventDefault(),Z()}})),a.createElement(M.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:_},a.createElement(G,{items:m,tabIndex:_?-1:0,onItemClick:n,activePath:o,level:i+1})))}var W=n(3919),R=n(9471);const V="menuExternalLink_NmtK";function z(e){let{item:t,onItemClick:n,activePath:o,level:i,index:s,...d}=e;const{href:m,label:u,className:b,autoAddBaseUrl:p}=t,h=(0,c._F)(t,o),E=(0,W.Z)(m);return a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(i),"menu__list-item",b),key:u},a.createElement(F.Z,(0,S.Z)({className:(0,l.Z)("menu__link",!E&&V,{"menu__link--active":h}),autoAddBaseUrl:p,"aria-current":h?"page":void 0,to:m},E&&{onClick:n?()=>n(t):void 0},d),u,!E&&a.createElement(R.Z,null)))}const U="menuHtmlItem_M9Kj";function K(e){let{item:t,level:n,index:o}=e;const{value:i,defaultStyle:c,className:s}=t;return a.createElement("li",{className:(0,l.Z)(r.k.docs.docSidebarItemLink,r.k.docs.docSidebarItemLinkLevel(n),c&&[U,"menu__list-item"],s),key:o,dangerouslySetInnerHTML:{__html:i}})}function j(e){let{item:t,...n}=e;switch(t.type){case"category":return a.createElement(D,(0,S.Z)({item:t},n));case"html":return a.createElement(K,(0,S.Z)({item:t},n));default:return a.createElement(z,(0,S.Z)({item:t},n))}}function q(e){let{items:t,...n}=e;return a.createElement(A,null,t.map(((e,t)=>a.createElement(j,(0,S.Z)({key:t,item:e,index:t},n)))))}const G=(0,a.memo)(q),Y="menu_SIkG",O="menuWithAnnouncementBar_GW3s";function X(e){let{path:t,sidebar:n,className:o}=e;const i=function(){const{isActive:e}=(0,T.nT)(),[t,n]=(0,a.useState)(e);return(0,b.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return a.createElement("nav",{"aria-label":(0,u.I)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,l.Z)("menu thin-scrollbar",Y,i&&O,o)},a.createElement("ul",{className:(0,l.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(G,{items:n,activePath:t,level:1})))}const J="sidebar_njMd",Q="sidebarWithHideableNavbar_wUlq",$="sidebarHidden_VK0M",ee="sidebarLogo_isFc";function te(e){let{path:t,sidebar:n,onCollapse:o,isHidden:r}=e;const{navbar:{hideOnScroll:i},docs:{sidebar:{hideable:c}}}=(0,k.L)();return a.createElement("div",{className:(0,l.Z)(J,i&&Q,r&&$)},i&&a.createElement(C.Z,{tabIndex:-1,className:ee}),a.createElement(X,{path:t,sidebar:n}),c&&a.createElement(x,{onClick:o}))}const ne=a.memo(te);var ae=n(3102),le=n(3163);const oe=e=>{let{sidebar:t,path:n}=e;const o=(0,le.e)();return a.createElement("ul",{className:(0,l.Z)(r.k.docs.docSidebarMenu,"menu__list")},a.createElement(G,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&o.toggle(),"link"===e.type&&o.toggle()},level:1}))};function re(e){return a.createElement(ae.Zo,{component:oe,props:e})}const ie=a.memo(re);function ce(e){const t=(0,_.i)(),n="desktop"===t||"ssr"===t,l="mobile"===t;return a.createElement(a.Fragment,null,n&&a.createElement(ne,e),l&&a.createElement(ie,e))}const se="expandButton_m80_",de="expandButtonIcon_BlDH";function me(e){let{toggleSidebar:t}=e;return a.createElement("div",{className:se,title:(0,u.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,u.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t},a.createElement(I,{className:de}))}const ue={docSidebarContainer:"docSidebarContainer_b6E3",docSidebarContainerHidden:"docSidebarContainerHidden_b3ry",sidebarViewport:"sidebarViewport_Xe31"};function be(e){var t;let{children:n}=e;const l=(0,d.V)();return a.createElement(a.Fragment,{key:null!=(t=null==l?void 0:l.name)?t:"noSidebar"},n)}function pe(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:o}=e;const{pathname:i}=(0,g.TH)(),[c,s]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{c&&s(!1),!c&&(0,v.n)()&&s(!0),o((e=>!e))}),[o,c]);return a.createElement("aside",{className:(0,l.Z)(r.k.docs.docSidebarContainer,ue.docSidebarContainer,n&&ue.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ue.docSidebarContainer)&&n&&s(!0)}},a.createElement(be,null,a.createElement("div",{className:(0,l.Z)(ue.sidebarViewport,c&&ue.sidebarViewportHidden)},a.createElement(ce,{sidebar:t,path:i,onCollapse:d,isHidden:c}),c&&a.createElement(me,{toggleSidebar:d}))))}const he={docMainContainer:"docMainContainer_gTbr",docMainContainerEnhanced:"docMainContainerEnhanced_Uz_u",docItemWrapperEnhanced:"docItemWrapperEnhanced_czyv"};function Ee(e){let{hiddenSidebarContainer:t,children:n}=e;const o=(0,d.V)();return a.createElement("main",{className:(0,l.Z)(he.docMainContainer,(t||!o)&&he.docMainContainerEnhanced)},a.createElement("div",{className:(0,l.Z)("container padding-top--md padding-bottom--lg",he.docItemWrapper,t&&he.docItemWrapperEnhanced)},n))}const fe="docPage__5DB",ve="docsWrapper_BCFX";function ge(e){let{children:t}=e;const n=(0,d.V)(),[l,o]=(0,a.useState)(!1);return a.createElement(m.Z,{wrapperClassName:ve},a.createElement(f,null),a.createElement("div",{className:fe},n&&a.createElement(pe,{sidebar:n.items,hiddenSidebarContainer:l,setHiddenSidebarContainer:o}),a.createElement(Ee,{hiddenSidebarContainer:l},t)))}var _e=n(4972),ke=n(197);function Ce(e){const{versionMetadata:t}=e;return a.createElement(a.Fragment,null,a.createElement(ke.Z,{version:t.version,tag:(0,i.os)(t.pluginId,t.version)}),a.createElement(o.d,null,t.noIndex&&a.createElement("meta",{name:"robots",content:"noindex, nofollow"})))}function Se(e){const{versionMetadata:t}=e,n=(0,c.hI)(e);if(!n)return a.createElement(_e.default,null);const{docElement:i,sidebarName:m,sidebarItems:u}=n;return a.createElement(a.Fragment,null,a.createElement(Ce,e),a.createElement(o.FG,{className:(0,l.Z)(r.k.wrapper.docsPages,r.k.page.docsDocPage,e.versionMetadata.className)},a.createElement(s.q,{version:t},a.createElement(d.b,{name:m,items:u},a.createElement(ge,null,i)))))}},4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>i});var a=n(7294),l=n(5999),o=n(833),r=n(7452);function i(){return a.createElement(a.Fragment,null,a.createElement(o.d,{title:(0,l.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(l.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}},4477:(e,t,n)=>{n.d(t,{E:()=>i,q:()=>r});var a=n(7294),l=n(902);const o=a.createContext(null);function r(e){let{children:t,version:n}=e;return a.createElement(o.Provider,{value:n},t)}function i(){const e=(0,a.useContext)(o);if(null===e)throw new l.i6("DocsVersionProvider");return e}}}]); \ No newline at end of file diff --git a/docs/assets/js/1c30975d.740a287b.js b/docs/assets/js/1c30975d.740a287b.js new file mode 100644 index 0000000000..1e659e8786 --- /dev/null +++ b/docs/assets/js/1c30975d.740a287b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3996],{8311:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=s(5893),o=s(1151);const i={title:"Customization"},r=void 0,c={id:"customization",title:"Customization",description:"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:",source:"@site/versioned_docs/version-v0.4.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v0.4.x/customization",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v0.4.x/exclusion"},next:{title:"Setup",permalink:"/eraser/docs/v0.4.x/setup"}},a={},l=[];function u(e){const t={code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"--job-cleanup-on-success-delay"}),": Duration to delay job deletion after successful runs. 0 means no delay. Defaults to ",(0,n.jsx)(t.code,{children:"0"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"--job-cleanup-on-error-delay"}),": Duration to delay job deletion after errored runs. 0 means no delay. Defaults to ",(0,n.jsx)(t.code,{children:"24h"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"--job-success-ratio"}),": Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to ",(0,n.jsx)(t.code,{children:"1.0"}),"."]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:'For duration, valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'})]})}function d(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},1151:(e,t,s)=>{s.d(t,{Z:()=>c,a:()=>r});var n=s(7294);const o={},i=n.createContext(o);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/1c30975d.c04b6b62.js b/docs/assets/js/1c30975d.c04b6b62.js deleted file mode 100644 index 3ee12dd87a..0000000000 --- a/docs/assets/js/1c30975d.c04b6b62.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3996],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=o,d=f["".concat(s,".").concat(m)]||f[m]||p[m]||a;return r?n.createElement(d,i(i({ref:t},u),{},{components:r})):n.createElement(d,i({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var c=2;c<a;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},115:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(7462),o=(r(7294),r(3905));const a={title:"Customization"},i=void 0,l={unversionedId:"customization",id:"version-v0.4.x/customization",title:"Customization",description:"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:",source:"@site/versioned_docs/version-v0.4.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v0.4.x/customization",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v0.4.x/exclusion"},next:{title:"Setup",permalink:"/eraser/docs/v0.4.x/setup"}},s={},c=[],u={toc:c};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"--job-cleanup-on-success-delay"),": Duration to delay job deletion after successful runs. 0 means no delay. Defaults to ",(0,o.kt)("inlineCode",{parentName:"li"},"0"),"."),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"--job-cleanup-on-error-delay"),": Duration to delay job deletion after errored runs. 0 means no delay. Defaults to ",(0,o.kt)("inlineCode",{parentName:"li"},"24h"),". "),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"--job-success-ratio"),": Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to ",(0,o.kt)("inlineCode",{parentName:"li"},"1.0"),". ")),(0,o.kt)("p",null,'For duration, valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/1dba1ecf.4673d8c6.js b/docs/assets/js/1dba1ecf.4673d8c6.js deleted file mode 100644 index 211171e9e7..0000000000 --- a/docs/assets/js/1dba1ecf.4673d8c6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2510],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function i(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=s(r),d=a,f=u["".concat(c,".").concat(d)]||u[d]||m[d]||o;return r?n.createElement(f,l(l({ref:t},p),{},{components:r})):n.createElement(f,l({ref:t},p))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,l=new Array(o);l[0]=u;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var s=2;s<o;s++)l[s]=r[s];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},3918:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>m,frontMatter:()=>o,metadata:()=>i,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const o={title:"Metrics"},l=void 0,i={unversionedId:"metrics",id:"metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/docs/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/next/metrics",draft:!1,tags:[],version:"current",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/next/customization"},next:{title:"Setup",permalink:"/eraser/docs/next/setup"}},c={},s=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}],p={toc:s};function m(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml"},"otelcollector.yaml"),", and the endpoint can be specified using the ",(0,a.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options"},"configmap"),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured."),(0,a.kt)("p",null,"Below is the list of metrics provided by Eraser per run:"),(0,a.kt)("h4",{id:"eraser"},"Eraser"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: images_removed_run_total\n - description: Total images removed by eraser\n")),(0,a.kt)("h4",{id:"scanner"},"Scanner"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: vulnerable_images_run_total\n - description: Total vulnerable images detected\n")),(0,a.kt)("h4",{id:"imagejob"},"ImageJob"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: imagejob_run_total\n - description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n - description: Total pods completed\n - name: pods_failed_run_total\n - description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n - description: Total time for ImageJobs scheduled to complete\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/1dba1ecf.d433b521.js b/docs/assets/js/1dba1ecf.d433b521.js new file mode 100644 index 0000000000..5e35a29bb3 --- /dev/null +++ b/docs/assets/js/1dba1ecf.d433b521.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2510],{7937:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(5893),o=n(1151);const a={title:"Metrics"},s=void 0,i={id:"metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/docs/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/next/metrics",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/next/customization"},next:{title:"Setup",permalink:"/eraser/docs/next/setup"}},c={},l=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}];function d(e){const t={a:"a",code:"code",h4:"h4",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,r.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml",children:"otelcollector.yaml"}),", and the endpoint can be specified using the ",(0,r.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options",children:"configmap"}),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at '",(0,r.jsx)(t.a,{href:"http://localhost:8889/metrics",children:"http://localhost:8889/metrics"}),"', but a separate exporter can also be configured."]}),"\n",(0,r.jsx)(t.p,{children:"Below is the list of metrics provided by Eraser per run:"}),"\n",(0,r.jsx)(t.h4,{id:"eraser",children:"Eraser"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n\t- name: images_removed_run_total\n\t\t- description: Total images removed by eraser\n"})}),"\n",(0,r.jsx)(t.h4,{id:"scanner",children:"Scanner"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: vulnerable_images_run_total\n \t- description: Total vulnerable images detected\n"})}),"\n",(0,r.jsx)(t.h4,{id:"imagejob",children:"ImageJob"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: imagejob_run_total\n \t- description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n \t- description: Total pods completed\n - name: pods_failed_run_total\n \t- description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n \t- description: Total time for ImageJobs scheduled to complete\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>i,a:()=>s});var r=n(7294);const o={},a=r.createContext(o);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/20cdecc4.5375813a.js b/docs/assets/js/20cdecc4.5375813a.js deleted file mode 100644 index 9ea829a256..0000000000 --- a/docs/assets/js/20cdecc4.5375813a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[391],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?l(Object(r),!0).forEach((function(n){a(e,n,r[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))}))}return e}function s(e,n){if(null==e)return{};var r,t,a=function(e,n){if(null==e)return{};var r,t,a={},l=Object.keys(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c<l;c++)o[c]=r[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,r)}u.displayName="MDXCreateElement"},4092:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"version-v0.5.x/manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v0.5.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v0.5.x/manual-removal",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v0.5.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v0.5.x/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n')),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," is a cluster-scoped resource and must be called imagelist. ",(0,a.kt)("inlineCode",{parentName:"p"},'"*"')," can be specified to remove all non-running images instead of individual images.")),(0,a.kt)("p",null,"Creating an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," should trigger an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageJob")," that will deploy Eraser pods on every node to perform the removal given the list of images."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n")),(0,a.kt)("p",null,"Pods will run to completion and the images will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n")),(0,a.kt)("p",null,"Verify the unused images are removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n")),(0,a.kt)("p",null,"If the image has been successfully removed, there will be no output."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/20cdecc4.7ca62856.js b/docs/assets/js/20cdecc4.7ca62856.js new file mode 100644 index 0000000000..cb0891948b --- /dev/null +++ b/docs/assets/js/20cdecc4.7ca62856.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[391],{2595:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v0.5.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v0.5.x/manual-removal",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v0.5.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v0.5.x/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"ImageList"})," is a cluster-scoped resource and must be called imagelist. ",(0,r.jsx)(n.code,{children:'"*"'})," can be specified to remove all non-running images instead of individual images."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Creating an ",(0,r.jsx)(n.code,{children:"ImageList"})," should trigger an ",(0,r.jsx)(n.code,{children:"ImageJob"})," that will deploy Eraser pods on every node to perform the removal given the list of images."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n"})}),"\n",(0,r.jsx)(n.p,{children:"Pods will run to completion and the images will be removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"ImageList"})," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"Verify the unused images are removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n"})}),"\n",(0,r.jsx)(n.p,{children:"If the image has been successfully removed, there will be no output."})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/22539a87.31d0f153.js b/docs/assets/js/22539a87.31d0f153.js new file mode 100644 index 0000000000..38ef51dc3e --- /dev/null +++ b/docs/assets/js/22539a87.31d0f153.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5964],{5174:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v0.4.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v0.4.x/",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v0.4.x/installation"}},c={},d=[];function l(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/22539a87.ca79dac7.js b/docs/assets/js/22539a87.ca79dac7.js deleted file mode 100644 index 47e01f4af9..0000000000 --- a/docs/assets/js/22539a87.ca79dac7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5964],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(c,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},9684:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",s={unversionedId:"introduction",id:"version-v0.4.x/introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v0.4.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v0.4.x/",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v0.4.x/installation"}},c={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/24e97898.33651e6b.js b/docs/assets/js/24e97898.33651e6b.js new file mode 100644 index 0000000000..70d531cbe9 --- /dev/null +++ b/docs/assets/js/24e97898.33651e6b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5781],{9480:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,l={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v0.4.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v0.4.x/architecture",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v0.4.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v0.4.x/manual-removal"}},o={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)(a.p,{children:"Note: metrics are not yet implemented in Eraser v0.4.x, but will be available in the upcoming v1.0.0 release."}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>l,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function l(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/24e97898.70b78e51.js b/docs/assets/js/24e97898.70b78e51.js deleted file mode 100644 index 5888fcca2f..0000000000 --- a/docs/assets/js/24e97898.70b78e51.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5781],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,v=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var s=2;s<i;s++)o[s]=r[s];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},7536:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"version-v0.4.x/architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v0.4.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v0.4.x/architecture",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v0.4.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v0.4.x/manual-removal"}},c={},s=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],u={toc:s};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("p",null,"Note: metrics are not yet implemented in Eraser v0.4.x, but will be available in the upcoming v1.0.0 release."),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/29ca1a0e.1424cf4d.js b/docs/assets/js/29ca1a0e.1424cf4d.js new file mode 100644 index 0000000000..9f5dff95e1 --- /dev/null +++ b/docs/assets/js/29ca1a0e.1424cf4d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5873],{8233:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var r=t(5893),s=t(1151);const o={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.1.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v1.1.x/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v1.1.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v1.1.x/trivy"}},i={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsxs)(n.p,{children:["To create a custom scanner for non-compliant images, use the following ",(0,r.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser-scanner-template/",children:"template"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In order to customize your scanner, start by creating a ",(0,r.jsx)(n.code,{children:"NewImageProvider()"}),". The ImageProvider interface can be found can be found ",(0,r.jsx)(n.a,{href:"../../pkg/scanners/template/scanner_template.go",children:"here"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,r.jsx)(n.code,{children:"ReceiveImages()"})," function. Process these images with your customized scanner and threshold, and use ",(0,r.jsx)(n.code,{children:"SendImages()"})," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,r.jsx)(n.code,{children:"Finish()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"When complete, provide your custom scanner image to Eraser in deployment."})]})}function u(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const s={},o=r.createContext(s);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/29ca1a0e.4d91cc87.js b/docs/assets/js/29ca1a0e.4d91cc87.js deleted file mode 100644 index 3924f82359..0000000000 --- a/docs/assets/js/29ca1a0e.4d91cc87.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5873],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,c(c({ref:t},p),{},{components:n})):r.createElement(f,c({ref:t},p))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var l=2;l<o;l++)c[l]=n[l];return r.createElement.apply(null,c)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},1261:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const o={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"version-v1.1.x/custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.1.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v1.1.x/custom-scanner",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v1.1.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v1.1.x/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],p={toc:l};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,a.kt)("p",null,"To create a custom scanner for non-compliant images, use the following ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser-scanner-template/"},"template"),"."),(0,a.kt)("p",null,"In order to customize your scanner, start by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},"NewImageProvider()"),". The ImageProvider interface can be found can be found ",(0,a.kt)("a",{parentName:"p",href:"../../pkg/scanners/template/scanner_template.go"},"here"),". "),(0,a.kt)("p",null,"The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,a.kt)("inlineCode",{parentName:"p"},"ReceiveImages()")," function. Process these images with your customized scanner and threshold, and use ",(0,a.kt)("inlineCode",{parentName:"p"},"SendImages()")," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,a.kt)("inlineCode",{parentName:"p"},"Finish()"),"."),(0,a.kt)("p",null,"When complete, provide your custom scanner image to Eraser in deployment."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/2c8b636f.733d78b2.js b/docs/assets/js/2c8b636f.733d78b2.js new file mode 100644 index 0000000000..d2e8520a39 --- /dev/null +++ b/docs/assets/js/2c8b636f.733d78b2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1763],{2958:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var s=i(5893),r=i(1151);const t={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Overview",source:"@site/versioned_docs/version-v0.4.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v0.4.x/releasing",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v0.4.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v0.4.x/custom-scanner"}},o={},c=[{value:"Overview",id:"overview",level:2},{value:"Versioning",id:"versioning",level:2},{value:"Building and releasing",id:"building-and-releasing",level:2},{value:"Publishing",id:"publishing",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.p,{children:"The release process consists of three phases: versioning, building, and publishing."}),"\n",(0,s.jsx)(n.p,{children:"Versioning involves maintaining the following files:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Makefile"})," - the Makefile contains a VERSION variable that defines the version of the project."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"manager.yaml"})," - the controller-manager deployment yaml contains the latest release tag image of the project."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"eraser.yaml"})," - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release."}),"\n",(0,s.jsx)(n.p,{children:"Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline."}),"\n",(0,s.jsxs)(n.p,{children:["Publishing involves creating a release tag and creating a new ",(0,s.jsx)(n.em,{children:"Release"})," on GitHub."]}),"\n",(0,s.jsx)(n.h2,{id:"versioning",children:"Versioning"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Obtain a copy of the repository."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git clone git@github.com:eraser-dev/eraser.git\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If this is a patch release for a release branch, check out applicable branch, such as ",(0,s.jsx)(n.code,{children:"release-0.1"}),". If not, branch should be ",(0,s.jsx)(n.code,{children:"main"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Execute the release-patch target to generate patch. Give the semantic version of the release:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make release-manifest NEWVERSION=vX.Y.Z\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Promote staging manifest to release."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make promote-staging-manifest\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If it's a new minor release (e.g. v0.",(0,s.jsx)(n.strong,{children:"4"}),".x -> 0.",(0,s.jsx)(n.strong,{children:"5"}),".0), tag docs to be versioned. Make sure to keep patch version as ",(0,s.jsx)(n.code,{children:".x"})," for a minor release."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make version-docs NEWVERSION=v0.5.x\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Preview the changes:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git status\ngit diff\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"building-and-releasing",children:"Building and releasing"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Commit the changes and push to remote repository to create a pull request."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'git checkout -b release-<NEW VERSION>\ngit commit -a -s -m "Prepare <NEW VERSION> release"\ngit push <YOUR FORK>\n'})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Once the PR is merged to ",(0,s.jsx)(n.code,{children:"main"})," or ",(0,s.jsx)(n.code,{children:"release"})," branch (",(0,s.jsx)(n.code,{children:"<BRANCH NAME>"})," below), tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(n.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser"})," and ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser-manager"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>a,a:()=>l});var s=i(7294);const r={},t=s.createContext(r);function l(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/2c8b636f.b2f1412e.js b/docs/assets/js/2c8b636f.b2f1412e.js deleted file mode 100644 index 0acd628bdd..0000000000 --- a/docs/assets/js/2c8b636f.b2f1412e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1763],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>g});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),p=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},c=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),u=p(r),g=a,d=u["".concat(s,".").concat(g)]||u[g]||m[g]||i;return r?n.createElement(d,l(l({ref:t},c),{},{components:r})):n.createElement(d,l({ref:t},c))}));function g(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=u;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var p=2;p<i;p++)l[p]=r[p];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},7395:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>m,frontMatter:()=>i,metadata:()=>o,toc:()=>p});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"version-v0.4.x/releasing",title:"Releasing",description:"Overview",source:"@site/versioned_docs/version-v0.4.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v0.4.x/releasing",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v0.4.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v0.4.x/custom-scanner"}},s={},p=[{value:"Overview",id:"overview",level:2},{value:"Versioning",id:"versioning",level:2},{value:"Building and releasing",id:"building-and-releasing",level:2},{value:"Publishing",id:"publishing",level:2}],c={toc:p};function m(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"overview"},"Overview"),(0,a.kt)("p",null,"The release process consists of three phases: versioning, building, and publishing."),(0,a.kt)("p",null,"Versioning involves maintaining the following files:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"Makefile")," - the Makefile contains a VERSION variable that defines the version of the project."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"manager.yaml")," - the controller-manager deployment yaml contains the latest release tag image of the project."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"eraser.yaml")," - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project.")),(0,a.kt)("p",null,"The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release."),(0,a.kt)("p",null,"Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline."),(0,a.kt)("p",null,"Publishing involves creating a release tag and creating a new ",(0,a.kt)("em",{parentName:"p"},"Release")," on GitHub."),(0,a.kt)("h2",{id:"versioning"},"Versioning"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Obtain a copy of the repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git clone git@github.com:eraser-dev/eraser.git\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"If this is a patch release for a release branch, check out applicable branch, such as ",(0,a.kt)("inlineCode",{parentName:"p"},"release-0.1"),". If not, branch should be ",(0,a.kt)("inlineCode",{parentName:"p"},"main"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Execute the release-patch target to generate patch. Give the semantic version of the release:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"make release-manifest NEWVERSION=vX.Y.Z\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Promote staging manifest to release."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"make promote-staging-manifest\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"If it's a new minor release (e.g. v0.",(0,a.kt)("strong",{parentName:"p"},"4"),".x -> 0.",(0,a.kt)("strong",{parentName:"p"},"5"),".0), tag docs to be versioned. Make sure to keep patch version as ",(0,a.kt)("inlineCode",{parentName:"p"},".x")," for a minor release."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"make version-docs NEWVERSION=v0.5.x\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Preview the changes:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git status\ngit diff\n")))),(0,a.kt)("h2",{id:"building-and-releasing"},"Building and releasing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Commit the changes and push to remote repository to create a pull request."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},'git checkout -b release-<NEW VERSION>\ngit commit -a -s -m "Prepare <NEW VERSION> release"\ngit push <YOUR FORK>\n'))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main")," or ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," branch (",(0,a.kt)("inlineCode",{parentName:"p"},"<BRANCH NAME>")," below), tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/2f4673e5.187f339b.js b/docs/assets/js/2f4673e5.187f339b.js new file mode 100644 index 0000000000..58b7dd98d2 --- /dev/null +++ b/docs/assets/js/2f4673e5.187f339b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[216],{4541:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(5893),o=n(1151);const a={title:"Metrics"},s=void 0,i={id:"metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.1.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/v1.1.x/metrics",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v1.1.x/customization"},next:{title:"Setup",permalink:"/eraser/docs/v1.1.x/setup"}},c={},l=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}];function d(e){const t={a:"a",code:"code",h4:"h4",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,r.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml",children:"otelcollector.yaml"}),", and the endpoint can be specified using the ",(0,r.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options",children:"configmap"}),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at '",(0,r.jsx)(t.a,{href:"http://localhost:8889/metrics",children:"http://localhost:8889/metrics"}),"', but a separate exporter can also be configured."]}),"\n",(0,r.jsx)(t.p,{children:"Below is the list of metrics provided by Eraser per run:"}),"\n",(0,r.jsx)(t.h4,{id:"eraser",children:"Eraser"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n\t- name: images_removed_run_total\n\t\t- description: Total images removed by eraser\n"})}),"\n",(0,r.jsx)(t.h4,{id:"scanner",children:"Scanner"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: vulnerable_images_run_total\n \t- description: Total vulnerable images detected\n"})}),"\n",(0,r.jsx)(t.h4,{id:"imagejob",children:"ImageJob"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: imagejob_run_total\n \t- description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n \t- description: Total pods completed\n - name: pods_failed_run_total\n \t- description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n \t- description: Total time for ImageJobs scheduled to complete\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>i,a:()=>s});var r=n(7294);const o={},a=r.createContext(o);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/2f4673e5.680a6df6.js b/docs/assets/js/2f4673e5.680a6df6.js deleted file mode 100644 index 68d042ddf7..0000000000 --- a/docs/assets/js/2f4673e5.680a6df6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[216],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(r),d=o,f=u["".concat(c,".").concat(d)]||u[d]||m[d]||a;return r?n.createElement(f,i(i({ref:t},p),{},{components:r})):n.createElement(f,i({ref:t},p))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s<a;s++)i[s]=r[s];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},184:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={title:"Metrics"},i=void 0,l={unversionedId:"metrics",id:"version-v1.1.x/metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.1.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/v1.1.x/metrics",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v1.1.x/customization"},next:{title:"Setup",permalink:"/eraser/docs/v1.1.x/setup"}},c={},s=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}],p={toc:s};function m(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml"},"otelcollector.yaml"),", and the endpoint can be specified using the ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options"},"configmap"),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured."),(0,o.kt)("p",null,"Below is the list of metrics provided by Eraser per run:"),(0,o.kt)("h4",{id:"eraser"},"Eraser"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: images_removed_run_total\n - description: Total images removed by eraser\n")),(0,o.kt)("h4",{id:"scanner"},"Scanner"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: vulnerable_images_run_total\n - description: Total vulnerable images detected\n")),(0,o.kt)("h4",{id:"imagejob"},"ImageJob"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: imagejob_run_total\n - description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n - description: Total pods completed\n - name: pods_failed_run_total\n - description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n - description: Total time for ImageJobs scheduled to complete\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/30fb9660.273b686e.js b/docs/assets/js/30fb9660.273b686e.js new file mode 100644 index 0000000000..d93ef96bec --- /dev/null +++ b/docs/assets/js/30fb9660.273b686e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3902],{3370:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var i=t(5893),r=t(1151);const a={title:"FAQ"},s=void 0,o={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.3.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/faq",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/contributing"}},l={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,i.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"configmap"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"how-is-eraser-different-from-kubernetes-garbage-collection",children:"How is Eraser different from Kubernetes garbage collection?"}),"\n",(0,i.jsxs)(n.p,{children:["The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/",children:"Kubernetes documentation"}),", and configuration options can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/",children:"Kubelet documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There are a couple core benefits to using Eraser for image cleanup:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Eraser can be configured to use image vulnerability data when making determinations on image removal"}),"\n",(0,i.jsx)(n.li,{children:"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>o,a:()=>s});var i=t(7294);const r={},a=i.createContext(r);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/30fb9660.e3f700a3.js b/docs/assets/js/30fb9660.e3f700a3.js deleted file mode 100644 index 7c9314da39..0000000000 --- a/docs/assets/js/30fb9660.e3f700a3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3902],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),b=a,g=f["".concat(s,".").concat(b)]||f[b]||p[b]||i;return r?n.createElement(g,o(o({ref:t},u),{},{components:r})):n.createElement(g,o({ref:t},u))}));function b(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c<i;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},9434:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"version-v1.3.x/faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.3.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/faq",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,a.kt)("p",null,"Eraser currently targets ",(0,a.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,a.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,a.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"configmap"),"."),(0,a.kt)("h2",{id:"how-is-eraser-different-from-kubernetes-garbage-collection"},"How is Eraser different from Kubernetes garbage collection?"),(0,a.kt)("p",null,"The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/"},"Kubernetes documentation"),", and configuration options can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/"},"Kubelet documentation"),". "),(0,a.kt)("p",null,"There are a couple core benefits to using Eraser for image cleanup:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Eraser can be configured to use image vulnerability data when making determinations on image removal"),(0,a.kt)("li",{parentName:"ul"},"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/34f2f592.2d883d56.js b/docs/assets/js/34f2f592.2d883d56.js new file mode 100644 index 0000000000..1402c9cef0 --- /dev/null +++ b/docs/assets/js/34f2f592.2d883d56.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9269],{5579:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var t=a(5893),s=a(1151);const l={title:"Quick Start"},r=void 0,i={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v0.5.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v0.5.x/quick-start",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v0.5.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v0.5.x/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,t.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,t.jsxs)(n.p,{children:["After following the ",(0,t.jsx)(n.a,{href:"/eraser/docs/v0.5.x/installation",children:"install instructions"}),", we'll apply a demo ",(0,t.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,t.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,t.jsxs)(n.p,{children:["First, apply the ",(0,t.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, verify that the Pods are running or completed. After the ",(0,t.jsx)(n.code,{children:"alpine"})," Pods complete, you may see a ",(0,t.jsx)(n.code,{children:"CrashLoopBackoff"})," status. This is expected behavior from the ",(0,t.jsx)(n.code,{children:"alpine"})," image and can be ignored for the tutorial."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n"})}),"\n",(0,t.jsx)(n.p,{children:"Delete the DaemonSet:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl delete daemonset alpine\n"})}),"\n",(0,t.jsx)(n.p,{children:"Verify that the Pods have been deleted:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNo resources found in default namespace.\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To verify that the ",(0,t.jsx)(n.code,{children:"alpine"})," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."]}),"\n",(0,t.jsx)(n.p,{children:"List the nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n"})}),"\n",(0,t.jsxs)(n.p,{children:["List the images then filter for ",(0,t.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,t.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by ",(0,t.jsx)(n.code,{children:"--repeat-period"})," argument to ",(0,t.jsx)(n.code,{children:"eraser-controller-manager"}),". The default interval is 24 hours (",(0,t.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,t.jsx)(n.p,{children:"Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,t.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by removing the ",(0,t.jsx)(n.code,{children:"--scanner-image"})," argument. If you are deploying with Helm, use ",(0,t.jsx)(n.code,{children:'--set scanner.image.repository=""'})," to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser."]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>i,a:()=>r});var t=a(7294);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/34f2f592.86fae0eb.js b/docs/assets/js/34f2f592.86fae0eb.js deleted file mode 100644 index 719769bf00..0000000000 --- a/docs/assets/js/34f2f592.86fae0eb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9269],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function i(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,o(o({ref:n},p),{},{components:t})):a.createElement(k,o({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,o=new Array(l);o[0]=m;var i={};for(var s in n)hasOwnProperty.call(n,s)&&(i[s]=n[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,o[1]=i;for(var c=2;c<l;c++)o[c]=t[c];return a.createElement.apply(null,o)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},5374:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},o=void 0,i={unversionedId:"quick-start",id:"version-v0.5.x/quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v0.5.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v0.5.x/quick-start",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v0.5.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v0.5.x/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/v0.5.x/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n")),(0,r.kt)("p",null,"Next, verify that the Pods are running or completed. After the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," Pods complete, you may see a ",(0,r.kt)("inlineCode",{parentName:"p"},"CrashLoopBackoff")," status. This is expected behavior from the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," image and can be ignored for the tutorial."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n")),(0,r.kt)("p",null,"Delete the DaemonSet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl delete daemonset alpine\n")),(0,r.kt)("p",null,"Verify that the Pods have been deleted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNo resources found in default namespace.\n")),(0,r.kt)("p",null,"To verify that the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."),(0,r.kt)("p",null,"List the nodes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by ",(0,r.kt)("inlineCode",{parentName:"p"},"--repeat-period")," argument to ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-controller-manager"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by removing the ",(0,r.kt)("inlineCode",{parentName:"p"},"--scanner-image")," argument. If you are deploying with Helm, use ",(0,r.kt)("inlineCode",{parentName:"p"},'--set scanner.image.repository=""')," to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/3847b3ea.43247e52.js b/docs/assets/js/3847b3ea.43247e52.js new file mode 100644 index 0000000000..db63a9fa4f --- /dev/null +++ b/docs/assets/js/3847b3ea.43247e52.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5581],{388:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/docs/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/next/setup",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/next/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/next/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/3847b3ea.5b5ccf89.js b/docs/assets/js/3847b3ea.5b5ccf89.js deleted file mode 100644 index fb6d598b54..0000000000 --- a/docs/assets/js/3847b3ea.5b5ccf89.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5581],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m<l;m++)i[m]=n[m];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}k.displayName="MDXCreateElement"},1959:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/docs/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/next/setup",draft:!1,tags:[],version:"current",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/next/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/next/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-remover"))),(0,r.kt)("p",null,"Builds the docker image for eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-remover"))),(0,r.kt)("p",null,"Builds the docker image for the eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/3a1ed2bb.12630a9f.js b/docs/assets/js/3a1ed2bb.12630a9f.js deleted file mode 100644 index eac8a35ad3..0000000000 --- a/docs/assets/js/3a1ed2bb.12630a9f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2389],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),b=a,g=f["".concat(s,".").concat(b)]||f[b]||p[b]||i;return r?n.createElement(g,o(o({ref:t},u),{},{components:r})):n.createElement(g,o({ref:t},u))}));function b(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c<i;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},2308:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"version-v1.2.x/faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.2.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v1.2.x/faq",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v1.2.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v1.2.x/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,a.kt)("p",null,"Eraser currently targets ",(0,a.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,a.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,a.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"configmap"),"."),(0,a.kt)("h2",{id:"how-is-eraser-different-from-kubernetes-garbage-collection"},"How is Eraser different from Kubernetes garbage collection?"),(0,a.kt)("p",null,"The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/"},"Kubernetes documentation"),", and configuration options can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/"},"Kubelet documentation"),". "),(0,a.kt)("p",null,"There are a couple core benefits to using Eraser for image cleanup:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Eraser can be configured to use image vulnerability data when making determinations on image removal"),(0,a.kt)("li",{parentName:"ul"},"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/3a1ed2bb.18ad5ad5.js b/docs/assets/js/3a1ed2bb.18ad5ad5.js new file mode 100644 index 0000000000..3884151acc --- /dev/null +++ b/docs/assets/js/3a1ed2bb.18ad5ad5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2389],{7748:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var i=t(5893),r=t(1151);const a={title:"FAQ"},s=void 0,o={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.2.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v1.2.x/faq",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v1.2.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v1.2.x/contributing"}},l={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,i.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"configmap"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"how-is-eraser-different-from-kubernetes-garbage-collection",children:"How is Eraser different from Kubernetes garbage collection?"}),"\n",(0,i.jsxs)(n.p,{children:["The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/",children:"Kubernetes documentation"}),", and configuration options can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/",children:"Kubelet documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There are a couple core benefits to using Eraser for image cleanup:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Eraser can be configured to use image vulnerability data when making determinations on image removal"}),"\n",(0,i.jsx)(n.li,{children:"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>o,a:()=>s});var i=t(7294);const r={},a=i.createContext(r);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/3b8c55ea.4ab0bf60.js b/docs/assets/js/3b8c55ea.4ab0bf60.js new file mode 100644 index 0000000000..e6a888179e --- /dev/null +++ b/docs/assets/js/3b8c55ea.4ab0bf60.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3217],{6995:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var s=n(5893),a=n(1151);const r={title:"Installation"},i=void 0,l={id:"installation",title:"Installation",description:"Manifest",source:"@site/docs/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/next/installation",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/next/"},next:{title:"Quick Start",permalink:"/eraser/docs/next/quick-start"}},o={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>l,a:()=>i});var s=n(7294);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/3b8c55ea.d50f0d5a.js b/docs/assets/js/3b8c55ea.d50f0d5a.js deleted file mode 100644 index 641beaac4b..0000000000 --- a/docs/assets/js/3b8c55ea.d50f0d5a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3217],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function i(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,l(l({ref:t},p),{},{components:r})):n.createElement(d,l({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,l=new Array(o);l[0]=f;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,l[1]=i;for(var c=2;c<o;c++)l[c]=r[c];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},9250:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},l=void 0,i={unversionedId:"installation",id:"installation",title:"Installation",description:"Manifest",source:"@site/docs/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/next/installation",draft:!1,tags:[],version:"current",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/next/"},next:{title:"Quick Start",permalink:"/eraser/docs/next/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/3e4c86d4.0b3602b2.js b/docs/assets/js/3e4c86d4.0b3602b2.js new file mode 100644 index 0000000000..4d70bfa985 --- /dev/null +++ b/docs/assets/js/3e4c86d4.0b3602b2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8180],{9424:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.1.x","label":"v1.1.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v1.1.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v1.1.x/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/v1.1.x/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/v1.1.x/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/v1.1.x/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v1.1.x/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/v1.1.x/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/v1.1.x/customization","docId":"customization","unlisted":false},{"type":"link","label":"Metrics","href":"/eraser/docs/v1.1.x/metrics","docId":"metrics","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v1.1.x/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/v1.1.x/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v1.1.x/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/v1.1.x/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v1.1.x/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/v1.1.x/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v1.1.x/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/3e4c86d4.eaafa28e.js b/docs/assets/js/3e4c86d4.eaafa28e.js deleted file mode 100644 index 76ce12d19d..0000000000 --- a/docs/assets/js/3e4c86d4.eaafa28e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8180],{9424:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.1.x","label":"v1.1.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v1.1.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v1.1.x/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/v1.1.x/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/v1.1.x/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/v1.1.x/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v1.1.x/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/v1.1.x/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/v1.1.x/customization","docId":"customization"},{"type":"link","label":"Metrics","href":"/eraser/docs/v1.1.x/metrics","docId":"metrics"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v1.1.x/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/v1.1.x/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v1.1.x/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/v1.1.x/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v1.1.x/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/v1.1.x/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v1.1.x/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/3fcb412e.54c127a8.js b/docs/assets/js/3fcb412e.54c127a8.js new file mode 100644 index 0000000000..fa9dc15e53 --- /dev/null +++ b/docs/assets/js/3fcb412e.54c127a8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3242],{3221:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var s=n(5893),r=n(1151);const a={title:"Installation"},i=void 0,o={id:"installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v0.4.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v0.4.x/installation",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v0.4.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v0.4.x/quick-start"}},l={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.4.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>i});var s=n(7294);const r={},a=s.createContext(r);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/3fcb412e.d61d4ab6.js b/docs/assets/js/3fcb412e.d61d4ab6.js deleted file mode 100644 index 2c0f15a34f..0000000000 --- a/docs/assets/js/3fcb412e.d61d4ab6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3242],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,i(i({ref:t},p),{},{components:r})):n.createElement(d,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<o;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},1450:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},i=void 0,l={unversionedId:"installation",id:"version-v0.4.x/installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v0.4.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v0.4.x/installation",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v0.4.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v0.4.x/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.4.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/422308df.b9cbb4dc.js b/docs/assets/js/422308df.b9cbb4dc.js new file mode 100644 index 0000000000..4f4abe8c5c --- /dev/null +++ b/docs/assets/js/422308df.b9cbb4dc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4642],{1865:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.2.x","label":"v1.2.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v1.2.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v1.2.x/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/v1.2.x/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/v1.2.x/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/v1.2.x/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v1.2.x/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/v1.2.x/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/v1.2.x/customization","docId":"customization","unlisted":false},{"type":"link","label":"Metrics","href":"/eraser/docs/v1.2.x/metrics","docId":"metrics","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v1.2.x/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/v1.2.x/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v1.2.x/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/v1.2.x/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v1.2.x/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/v1.2.x/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v1.2.x/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/422308df.c748cc2d.js b/docs/assets/js/422308df.c748cc2d.js deleted file mode 100644 index ca82727f7b..0000000000 --- a/docs/assets/js/422308df.c748cc2d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4642],{1865:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.2.x","label":"v1.2.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v1.2.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v1.2.x/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/v1.2.x/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/v1.2.x/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/v1.2.x/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v1.2.x/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/v1.2.x/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/v1.2.x/customization","docId":"customization"},{"type":"link","label":"Metrics","href":"/eraser/docs/v1.2.x/metrics","docId":"metrics"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v1.2.x/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/v1.2.x/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v1.2.x/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/v1.2.x/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v1.2.x/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/v1.2.x/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v1.2.x/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/4351fb58.2ba23a80.js b/docs/assets/js/4351fb58.2ba23a80.js deleted file mode 100644 index 9510ce82a8..0000000000 --- a/docs/assets/js/4351fb58.2ba23a80.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7551],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(r),f=i,v=m["".concat(s,".").concat(f)]||m[f]||p[f]||a;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var c=2;c<a;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},1153:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const a={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"version-v1.0.x/faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.0.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v1.0.x/faq",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v1.0.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v1.0.x/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,i.kt)("p",null,"Eraser currently targets ",(0,i.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,i.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"configmap"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/4351fb58.d28caec9.js b/docs/assets/js/4351fb58.d28caec9.js new file mode 100644 index 0000000000..ff3119ac09 --- /dev/null +++ b/docs/assets/js/4351fb58.d28caec9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7551],{2435:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var i=t(5893),r=t(1151);const s={title:"FAQ"},a=void 0,o={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.0.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v1.0.x/faq",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v1.0.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v1.0.x/contributing"}},l={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,i.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"configmap"}),"."]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>o,a:()=>a});var i=t(7294);const r={},s=i.createContext(r);function a(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/44b2adf6.28ae2c3b.js b/docs/assets/js/44b2adf6.28ae2c3b.js deleted file mode 100644 index 2ad4d72501..0000000000 --- a/docs/assets/js/44b2adf6.28ae2c3b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8841],{3905:(e,r,t)=>{t.d(r,{Zo:()=>l,kt:()=>f});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?i(Object(t),!0).forEach((function(r){o(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function c(e,r){if(null==e)return{};var t,n,o=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},l=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},v=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),v=p(t),f=o,y=v["".concat(s,".").concat(f)]||v[f]||u[f]||i;return t?n.createElement(y,a(a({ref:r},l),{},{components:t})):n.createElement(y,a({ref:r},l))}));function f(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=v;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p<i;p++)a[p]=t[p];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}v.displayName="MDXCreateElement"},2650:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i={title:"Trivy"},a=void 0,c={unversionedId:"trivy",id:"version-v1.3.x/trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.3.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/trivy",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/faq"}},s={},p=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],l={toc:p};function u(e){let{components:r,...t}=e;return(0,o.kt)("wrapper",(0,n.Z)({},l,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,o.kt)("p",null,"The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"Customization")," for more details on configuring the scanner."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/44b2adf6.95473760.js b/docs/assets/js/44b2adf6.95473760.js new file mode 100644 index 0000000000..43131dfb7e --- /dev/null +++ b/docs/assets/js/44b2adf6.95473760.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8841],{2947:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>v,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var n=r(5893),i=r(1151);const o={title:"Trivy"},s=void 0,a={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.3.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/trivy",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/faq"}},c={},d=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,n.jsxs)(t.p,{children:["The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,n.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"Customization"})," for more details on configuring the scanner."]})]})}function v(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},1151:(e,t,r)=>{r.d(t,{Z:()=>a,a:()=>s});var n=r(7294);const i={},o=n.createContext(i);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/48ae5635.4f79be50.js b/docs/assets/js/48ae5635.4f79be50.js deleted file mode 100644 index 6ddd4f3dd7..0000000000 --- a/docs/assets/js/48ae5635.4f79be50.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9212],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(r),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=r[l];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}d.displayName="MDXCreateElement"},6954:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"version-v0.4.x/contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v0.4.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v0.4.x/contributing",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v0.4.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v0.4.x/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/48ae5635.ae8b4c4e.js b/docs/assets/js/48ae5635.ae8b4c4e.js new file mode 100644 index 0000000000..be8d86ca9e --- /dev/null +++ b/docs/assets/js/48ae5635.ae8b4c4e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9212],{4397:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v0.4.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v0.4.x/contributing",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v0.4.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v0.4.x/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4972.e3352a90.js b/docs/assets/js/4972.e3352a90.js deleted file mode 100644 index 0a8afbec67..0000000000 --- a/docs/assets/js/4972.e3352a90.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4972],{4972:(e,t,n)=>{n.r(t),n.d(t,{default:()=>i});var a=n(7294),l=n(5999),o=n(833),r=n(7452);function i(){return a.createElement(a.Fragment,null,a.createElement(o.d,{title:(0,l.I)({id:"theme.NotFound.title",message:"Page Not Found"})}),a.createElement(r.Z,null,a.createElement("main",{className:"container margin-vert--xl"},a.createElement("div",{className:"row"},a.createElement("div",{className:"col col--6 col--offset-3"},a.createElement("h1",{className:"hero__title"},a.createElement(l.Z,{id:"theme.NotFound.title",description:"The title of the 404 page"},"Page Not Found")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page"},"We could not find what you were looking for.")),a.createElement("p",null,a.createElement(l.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page"},"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))))}}}]); \ No newline at end of file diff --git a/docs/assets/js/4d54d076.6a163bd0.js b/docs/assets/js/4d54d076.6a163bd0.js deleted file mode 100644 index a0d86719a5..0000000000 --- a/docs/assets/js/4d54d076.6a163bd0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7080],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),m=l(r),d=o,f=m["".concat(s,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=r[l];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},1933:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/docs/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/next/contributing",draft:!1,tags:[],version:"current",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/next/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/next/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/4d54d076.d5641f32.js b/docs/assets/js/4d54d076.d5641f32.js new file mode 100644 index 0000000000..4ee823c0fe --- /dev/null +++ b/docs/assets/js/4d54d076.d5641f32.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7080],{4651:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/docs/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/next/contributing",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/next/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/next/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4eac74de.cd66025d.js b/docs/assets/js/4eac74de.cd66025d.js new file mode 100644 index 0000000000..7c164be119 --- /dev/null +++ b/docs/assets/js/4eac74de.cd66025d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2547],{9084:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>u});var r=t(5893),o=t(1151);const s={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v0.4.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v0.4.x/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v0.4.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v0.4.x/trivy"}},i={},u=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsx)(n.p,{children:"To create a custom scanner for non-compliant images, provide your scanner image to Eraser in deployment."}),"\n",(0,r.jsxs)(n.p,{children:["In order for the custom scanner to communicate with the collector and eraser containers, utilize ",(0,r.jsx)(n.code,{children:"ReadCollectScanPipe()"})," to get the list of all non-running images to scan from collector. Then, use ",(0,r.jsx)(n.code,{children:"WriteScanErasePipe()"})," to pass the images found non-compliant by your scanner to eraser for removal. Both functions can be found in ",(0,r.jsx)(n.a,{href:"../../pkg/utils/utils.go",children:"util"}),"."]})]})}function d(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const o={},s=r.createContext(o);function a(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4eac74de.fb8596ee.js b/docs/assets/js/4eac74de.fb8596ee.js deleted file mode 100644 index 78550f4c81..0000000000 --- a/docs/assets/js/4eac74de.fb8596ee.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2547],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=l(n),f=o,d=m["".concat(s,".").concat(f)]||m[f]||p[f]||a;return n?r.createElement(d,c(c({ref:t},u),{},{components:n})):r.createElement(d,c({ref:t},u))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,c=new Array(a);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:o,c[1]=i;for(var l=2;l<a;l++)c[l]=n[l];return r.createElement.apply(null,c)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},8475:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const a={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"version-v0.4.x/custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v0.4.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v0.4.x/custom-scanner",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v0.4.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v0.4.x/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,o.kt)("p",null,"To create a custom scanner for non-compliant images, provide your scanner image to Eraser in deployment."),(0,o.kt)("p",null,"In order for the custom scanner to communicate with the collector and eraser containers, utilize ",(0,o.kt)("inlineCode",{parentName:"p"},"ReadCollectScanPipe()")," to get the list of all non-running images to scan from collector. Then, use ",(0,o.kt)("inlineCode",{parentName:"p"},"WriteScanErasePipe()")," to pass the images found non-compliant by your scanner to eraser for removal. Both functions can be found in ",(0,o.kt)("a",{parentName:"p",href:"../../pkg/utils/utils.go"},"util"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/4fa03c51.7f9609b5.js b/docs/assets/js/4fa03c51.7f9609b5.js new file mode 100644 index 0000000000..52e648985d --- /dev/null +++ b/docs/assets/js/4fa03c51.7f9609b5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7395],{2447:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/docs/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/next/manual-removal",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/next/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/next/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"ImageList"})," is a cluster-scoped resource and must be called imagelist. ",(0,r.jsx)(n.code,{children:'"*"'})," can be specified to remove all non-running images instead of individual images."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Creating an ",(0,r.jsx)(n.code,{children:"ImageList"})," should trigger an ",(0,r.jsx)(n.code,{children:"ImageJob"})," that will deploy Eraser pods on every node to perform the removal given the list of images."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n"})}),"\n",(0,r.jsx)(n.p,{children:"Pods will run to completion and the images will be removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"ImageList"})," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"Verify the unused images are removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n"})}),"\n",(0,r.jsx)(n.p,{children:"If the image has been successfully removed, there will be no output."})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4fa03c51.ad054cf8.js b/docs/assets/js/4fa03c51.ad054cf8.js deleted file mode 100644 index e1a6c80c1f..0000000000 --- a/docs/assets/js/4fa03c51.ad054cf8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7395],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?l(Object(r),!0).forEach((function(n){a(e,n,r[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))}))}return e}function s(e,n){if(null==e)return{};var r,t,a=function(e,n){if(null==e)return{};var r,t,a={},l=Object.keys(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c<l;c++)o[c]=r[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,r)}u.displayName="MDXCreateElement"},7422:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/docs/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/next/manual-removal",draft:!1,tags:[],version:"current",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/next/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/next/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n')),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," is a cluster-scoped resource and must be called imagelist. ",(0,a.kt)("inlineCode",{parentName:"p"},'"*"')," can be specified to remove all non-running images instead of individual images.")),(0,a.kt)("p",null,"Creating an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," should trigger an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageJob")," that will deploy Eraser pods on every node to perform the removal given the list of images."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n")),(0,a.kt)("p",null,"Pods will run to completion and the images will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n")),(0,a.kt)("p",null,"Verify the unused images are removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n")),(0,a.kt)("p",null,"If the image has been successfully removed, there will be no output."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/4fb2362d.43d62e16.js b/docs/assets/js/4fb2362d.43d62e16.js deleted file mode 100644 index 629b2ff8f0..0000000000 --- a/docs/assets/js/4fb2362d.43d62e16.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4248],{6198:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.3.x","label":"v1.3.x","banner":null,"badge":true,"noIndex":false,"className":"docs-version-v1.3.x","isLast":true,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/customization","docId":"customization"},{"type":"link","label":"Metrics","href":"/eraser/docs/metrics","docId":"metrics"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"release-management":{"id":"release-management","title":"Release Management","description":"Overview"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/4fb2362d.5120e8b9.js b/docs/assets/js/4fb2362d.5120e8b9.js new file mode 100644 index 0000000000..4f2cfe0617 --- /dev/null +++ b/docs/assets/js/4fb2362d.5120e8b9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4248],{6198:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.3.x","label":"v1.3.x","banner":null,"badge":true,"noIndex":false,"className":"docs-version-v1.3.x","isLast":true,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/customization","docId":"customization","unlisted":false},{"type":"link","label":"Metrics","href":"/eraser/docs/metrics","docId":"metrics","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"release-management":{"id":"release-management","title":"Release Management","description":"Overview"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/5281b7a2.981f96dc.js b/docs/assets/js/5281b7a2.981f96dc.js new file mode 100644 index 0000000000..4a643a2797 --- /dev/null +++ b/docs/assets/js/5281b7a2.981f96dc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5927],{2589:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,o={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/docs/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/next/architecture",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/next/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/next/manual-removal"}},l={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>o,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/5281b7a2.ceaf1ffc.js b/docs/assets/js/5281b7a2.ceaf1ffc.js deleted file mode 100644 index 82f17d89f6..0000000000 --- a/docs/assets/js/5281b7a2.ceaf1ffc.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5927],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),u=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},s=function(e){var t=u(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=u(r),d=a,f=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(f,o(o({ref:t},s),{},{components:r})):n.createElement(f,o({ref:t},s))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var u=2;u<i;u++)o[u]=r[u];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},1527:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>u});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/docs/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/next/architecture",draft:!1,tags:[],version:"current",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/next/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/next/manual-removal"}},c={},u=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],s={toc:u};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/5603335d.05cbde15.js b/docs/assets/js/5603335d.05cbde15.js deleted file mode 100644 index 90ea50a8d7..0000000000 --- a/docs/assets/js/5603335d.05cbde15.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1031],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||p[d]||o;return n?r.createElement(f,c(c({ref:t},u),{},{components:n})):r.createElement(f,c({ref:t},u))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var l=2;l<o;l++)c[l]=n[l];return r.createElement.apply(null,c)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},1307:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>p,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const o={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/docs/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/next/custom-scanner",draft:!1,tags:[],version:"current",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/next/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/next/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],u={toc:l};function p(e){let{components:t,...o}=e;return(0,a.kt)("wrapper",(0,r.Z)({},u,o,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,a.kt)("p",null,"To create a custom scanner for non-compliant images, use the following ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser-scanner-template/"},"template"),"."),(0,a.kt)("p",null,"In order to customize your scanner, start by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},"NewImageProvider()"),". The ImageProvider interface can be found can be found ",(0,a.kt)("a",{target:"_blank",href:n(429).Z},"here"),". "),(0,a.kt)("p",null,"The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,a.kt)("inlineCode",{parentName:"p"},"ReceiveImages()")," function. Process these images with your customized scanner and threshold, and use ",(0,a.kt)("inlineCode",{parentName:"p"},"SendImages()")," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,a.kt)("inlineCode",{parentName:"p"},"Finish()"),"."),(0,a.kt)("p",null,"When complete, provide your custom scanner image to Eraser in deployment."))}p.isMDXComponent=!0},429:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/files/scanner_template-1354bd0e962dd16dc5001599d249b071.go"}}]); \ No newline at end of file diff --git a/docs/assets/js/5603335d.b23ecd98.js b/docs/assets/js/5603335d.b23ecd98.js new file mode 100644 index 0000000000..c06ed5d4a8 --- /dev/null +++ b/docs/assets/js/5603335d.b23ecd98.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1031],{2058:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>d});var r=t(5893),s=t(1151);const o={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/docs/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/next/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/next/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/next/trivy"}},i={},d=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsxs)(n.p,{children:["To create a custom scanner for non-compliant images, use the following ",(0,r.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser-scanner-template/",children:"template"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In order to customize your scanner, start by creating a ",(0,r.jsx)(n.code,{children:"NewImageProvider()"}),". The ImageProvider interface can be found can be found ",(0,r.jsx)(n.a,{target:"_blank","data-noBrokenLinkCheck":!0,href:t(429).Z+"",children:"here"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,r.jsx)(n.code,{children:"ReceiveImages()"})," function. Process these images with your customized scanner and threshold, and use ",(0,r.jsx)(n.code,{children:"SendImages()"})," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,r.jsx)(n.code,{children:"Finish()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"When complete, provide your custom scanner image to Eraser in deployment."})]})}function u(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},429:(e,n,t)=>{t.d(n,{Z:()=>r});const r=t.p+"assets/files/scanner_template-1354bd0e962dd16dc5001599d249b071.go"},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const s={},o=r.createContext(s);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/59e5a646.d59d85e0.js b/docs/assets/js/59e5a646.d59d85e0.js new file mode 100644 index 0000000000..e1eaf25435 --- /dev/null +++ b/docs/assets/js/59e5a646.d59d85e0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3022],{3164:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.1.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v1.1.x/setup",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/v1.1.x/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/v1.1.x/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/59e5a646.e9edd18a.js b/docs/assets/js/59e5a646.e9edd18a.js deleted file mode 100644 index 015bf4cf1c..0000000000 --- a/docs/assets/js/59e5a646.e9edd18a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3022],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m<l;m++)i[m]=n[m];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}k.displayName="MDXCreateElement"},3065:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"version-v1.1.x/setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.1.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v1.1.x/setup",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/v1.1.x/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/v1.1.x/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-remover"))),(0,r.kt)("p",null,"Builds the docker image for eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-remover"))),(0,r.kt)("p",null,"Builds the docker image for the eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/5af9b662.48bb081f.js b/docs/assets/js/5af9b662.48bb081f.js new file mode 100644 index 0000000000..49b15ca5a6 --- /dev/null +++ b/docs/assets/js/5af9b662.48bb081f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5523],{7929:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=n(5893),t=n(1151);const i={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.0.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v1.0.x/releasing",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v1.0.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v1.0.x/custom-scanner"}},o={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2}];function d(e){const r={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.h2,{id:"create-release-pull-request",children:"Create Release Pull Request"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{children:["Go to ",(0,s.jsx)(r.code,{children:"create_release_pull_request"})," workflow under actions."]}),"\n",(0,s.jsx)(r.li,{children:"Select run workflow, and use the workflow from your branch."}),"\n",(0,s.jsx)(r.li,{children:"Input release version with the semantic version identifying the release."}),"\n",(0,s.jsx)(r.li,{children:"Click run workflow and review the PR created by github-actions."}),"\n"]}),"\n",(0,s.jsx)(r.h1,{id:"releasing",children:"Releasing"}),"\n",(0,s.jsxs)(r.ol,{start:"5",children:["\n",(0,s.jsxs)(r.li,{children:["\n",(0,s.jsxs)(r.p,{children:["Once the PR is merged to ",(0,s.jsx)(r.code,{children:"main"}),", tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(r.li,{children:["\n",(0,s.jsxs)(r.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(r.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser"}),", ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser-manager"}),", ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/collector"}),", and ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(r.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(r.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]})]})}function h(e={}){const{wrapper:r}={...(0,t.a)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,r,n)=>{n.d(r,{Z:()=>a,a:()=>l});var s=n(7294);const t={},i=s.createContext(t);function l(e){const r=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),s.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/5af9b662.988a70e9.js b/docs/assets/js/5af9b662.988a70e9.js deleted file mode 100644 index f71a78a65f..0000000000 --- a/docs/assets/js/5af9b662.988a70e9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5523],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(r),d=a,g=m["".concat(s,".").concat(d)]||m[d]||u[d]||i;return r?n.createElement(g,l(l({ref:t},p),{},{components:r})):n.createElement(g,l({ref:t},p))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c<i;c++)l[c]=r[c];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},4478:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"version-v1.0.x/releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.0.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v1.0.x/releasing",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v1.0.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v1.0.x/custom-scanner"}},s={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"create-release-pull-request"},"Create Release Pull Request"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Go to ",(0,a.kt)("inlineCode",{parentName:"li"},"create_release_pull_request")," workflow under actions."),(0,a.kt)("li",{parentName:"ol"},"Select run workflow, and use the workflow from your branch. "),(0,a.kt)("li",{parentName:"ol"},"Input release version with the semantic version identifying the release."),(0,a.kt)("li",{parentName:"ol"},"Click run workflow and review the PR created by github-actions.")),(0,a.kt)("h1",{id:"releasing"},"Releasing"),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main"),", tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/collector"),", and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-trivy-scanner")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/5bc37772.1188e660.js b/docs/assets/js/5bc37772.1188e660.js deleted file mode 100644 index 198a873488..0000000000 --- a/docs/assets/js/5bc37772.1188e660.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8084],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(r),d=a,g=m["".concat(s,".").concat(d)]||m[d]||u[d]||i;return r?n.createElement(g,l(l({ref:t},p),{},{components:r})):n.createElement(g,l({ref:t},p))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c<i;c++)l[c]=r[c];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},372:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"version-v1.2.x/releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.2.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v1.2.x/releasing",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v1.2.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v1.2.x/custom-scanner"}},s={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"create-release-pull-request"},"Create Release Pull Request"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Go to ",(0,a.kt)("inlineCode",{parentName:"li"},"create_release_pull_request")," workflow under actions."),(0,a.kt)("li",{parentName:"ol"},"Select run workflow, and use the workflow from your branch. "),(0,a.kt)("li",{parentName:"ol"},"Input release version with the semantic version identifying the release."),(0,a.kt)("li",{parentName:"ol"},"Click run workflow and review the PR created by github-actions.")),(0,a.kt)("h1",{id:"releasing"},"Releasing"),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main"),", tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/remover"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/collector"),", and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-trivy-scanner")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/5bc37772.c2ae9680.js b/docs/assets/js/5bc37772.c2ae9680.js new file mode 100644 index 0000000000..77aa9561f4 --- /dev/null +++ b/docs/assets/js/5bc37772.c2ae9680.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8084],{601:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=n(5893),t=n(1151);const i={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.2.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v1.2.x/releasing",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v1.2.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v1.2.x/custom-scanner"}},o={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2}];function d(e){const r={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.h2,{id:"create-release-pull-request",children:"Create Release Pull Request"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{children:["Go to ",(0,s.jsx)(r.code,{children:"create_release_pull_request"})," workflow under actions."]}),"\n",(0,s.jsx)(r.li,{children:"Select run workflow, and use the workflow from your branch."}),"\n",(0,s.jsx)(r.li,{children:"Input release version with the semantic version identifying the release."}),"\n",(0,s.jsx)(r.li,{children:"Click run workflow and review the PR created by github-actions."}),"\n"]}),"\n",(0,s.jsx)(r.h1,{id:"releasing",children:"Releasing"}),"\n",(0,s.jsxs)(r.ol,{start:"5",children:["\n",(0,s.jsxs)(r.li,{children:["\n",(0,s.jsxs)(r.p,{children:["Once the PR is merged to ",(0,s.jsx)(r.code,{children:"main"}),", tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(r.li,{children:["\n",(0,s.jsxs)(r.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(r.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/remover"}),", ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser-manager"}),", ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/collector"}),", and ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(r.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(r.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]})]})}function h(e={}){const{wrapper:r}={...(0,t.a)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,r,n)=>{n.d(r,{Z:()=>a,a:()=>l});var s=n(7294);const t={},i=s.createContext(t);function l(e){const r=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),s.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/5c838b7d.8c56c538.js b/docs/assets/js/5c838b7d.8c56c538.js deleted file mode 100644 index 6c1e4fae2f..0000000000 --- a/docs/assets/js/5c838b7d.8c56c538.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2242],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),m=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=m(e.components);return a.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),c=m(n),d=r,g=c["".concat(s,".").concat(d)]||c[d]||u[d]||o;return n?a.createElement(g,l(l({ref:t},p),{},{components:n})):a.createElement(g,l({ref:t},p))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=c;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var m=2;m<o;m++)l[m]=n[m];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}c.displayName="MDXCreateElement"},6874:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const o={title:"Customization"},l=void 0,i={unversionedId:"customization",id:"version-v1.3.x/customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.3.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/customization",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/metrics"}},s={},m=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}],p={toc:m};function u(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl edit configmap --namespace eraser-system eraser-manager-config\n")),(0,r.kt)("p",null,"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."),(0,r.kt)("h2",{id:"key-concepts"},"Key Concepts"),(0,r.kt)("h3",{id:"basic-architecture"},"Basic architecture"),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"manager")," runs as a pod in your cluster and manages ",(0,r.kt)("em",{parentName:"p"},"ImageJobs"),". Think of\nan ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Assessment"),(0,r.kt)("li",{parentName:"ol"},"Removal.")),(0,r.kt)("h3",{id:"scheduling"},"Scheduling"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," can either be created on-demand (see ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/manual-removal"},"Manual Removal"),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."),(0,r.kt)("h3",{id:"fault-tolerance"},"Fault Tolerance"),(0,r.kt)("p",null,"Because an ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.successRatio")," property to\n",(0,r.kt)("inlineCode",{parentName:"p"},"1.0"),". If 75% success sounds good to you, set it to ",(0,r.kt)("inlineCode",{parentName:"p"},"0.75"),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," report success, the job as\na whole will be marked as a failure."),(0,r.kt)("p",null,"This is mainly to help diagnose error conditions. As such, you can set\n",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.cleanup.delayOnFailure")," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."),(0,r.kt)("h3",{id:"excluding-nodes"},"Excluding Nodes"),(0,r.kt)("p",null,"For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter"),", but you can configure the behavior with\nthe options under ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.nodeFilter"),". The ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table")," provides more detail."),(0,r.kt)("h3",{id:"configuring-components"},"Configuring Components"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Collection (What is on the node?)"),(0,r.kt)("li",{parentName:"ol"},"Scanning (What images conform to the policy I've provided?)"),(0,r.kt)("li",{parentName:"ol"},"Removal (Remove images based on the results of the above)")),(0,r.kt)("p",null,"Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,r.kt)("em",{parentName:"p"},"ImageJobs")," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"The collector and/or scanner ",(0,r.kt)("inlineCode",{parentName:"li"},"components")," are enabled, AND"),(0,r.kt)("li",{parentName:"ol"},"The job was ",(0,r.kt)("em",{parentName:"li"},"not")," triggered manually by creating an ",(0,r.kt)("em",{parentName:"li"},"ImageList"),".")),(0,r.kt)("h3",{id:"swapping-out-components"},"Swapping out components"),(0,r.kt)("p",null,"The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.repo")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.tag"),",\nwhere ",(0,r.kt)("inlineCode",{parentName:"p"},"<component>")," is one of ",(0,r.kt)("inlineCode",{parentName:"p"},"collector"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"scanner"),", or ",(0,r.kt)("inlineCode",{parentName:"p"},"remover"),"."),(0,r.kt)("h2",{id:"universal-options"},"Universal Options"),(0,r.kt)("p",null,"The following portions of the configmap apply no matter how you spawn your\n",(0,r.kt)("em",{parentName:"p"},"ImageJob"),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'manager:\n runtime:\n name: containerd\n address: unix:///run/containerd/containerd.sock\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n')),(0,r.kt)("h2",{id:"component-options"},"Component Options"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n")),(0,r.kt)("h2",{id:"scanner-options"},"Scanner Options"),(0,r.kt)("p",null,"These options can be provided to ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.config"),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."),(0,r.kt)("p",null,"Below are the values recognized by the provided ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-trivy-scanner")," image.\nValues provided below are the defaults."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more information\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\n ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n")),(0,r.kt)("h2",{id:"detailed-options"},"Detailed Options"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Option"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"),(0,r.kt)("th",{parentName:"tr",align:null},"Default"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime.name"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."),(0,r.kt)("td",{parentName:"tr",align:null},"containerd")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime.address"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions."),(0,r.kt)("td",{parentName:"tr",align:null},"unix:///run/containerd/containerd.sock")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.otlpEndpoint"),(0,r.kt)("td",{parentName:"tr",align:null},"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.logLevel"),(0,r.kt)("td",{parentName:"tr",align:null},"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."),(0,r.kt)("td",{parentName:"tr",align:null},"info")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.repeatInterval"),(0,r.kt)("td",{parentName:"tr",align:null},"Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," at the interval provided."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.beginImmediately"),(0,r.kt)("td",{parentName:"tr",align:null},"If set to true, the fist ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable profiling for the manager's containers. This is for debugging with ",(0,r.kt)("inlineCode",{parentName:"td"},"go tool pprof"),"."),(0,r.kt)("td",{parentName:"tr",align:null},"false")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.port"),(0,r.kt)("td",{parentName:"tr",align:null},"The port on which to expose the profiling endpoint."),(0,r.kt)("td",{parentName:"tr",align:null},"6060")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.successRatio"),(0,r.kt)("td",{parentName:"tr",align:null},"The ratio of successful image jobs required before a cleanup is performed."),(0,r.kt)("td",{parentName:"tr",align:null},"1.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnSuccess"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a successful image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"0s")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnFailure"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a failed image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.pullSecrets"),(0,r.kt)("td",{parentName:"tr",align:null},"The image pull secrets to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.priorityClassName"),(0,r.kt)("td",{parentName:"tr",align:null},"The priority class to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.type"),(0,r.kt)("td",{parentName:"tr",align:null},'The type of node filter to use. Must be either "exclude" or "include".'),(0,r.kt)("td",{parentName:"tr",align:null},"exclude")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.selectors"),(0,r.kt)("td",{parentName:"tr",align:null},"A list of selectors used to filter nodes."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the collector component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/collector")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"7m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the scanner component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/eraser-trivy-scanner")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"1000m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"2Gi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.config"),(0,r.kt)("td",{parentName:"tr",align:null},"The configuration to pass to the scanner container, as a YAML string."),(0,r.kt)("td",{parentName:"tr",align:null},"See YAML below")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/remover")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"0")))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/5c838b7d.abeb9ef9.js b/docs/assets/js/5c838b7d.abeb9ef9.js new file mode 100644 index 0000000000..f96c441a39 --- /dev/null +++ b/docs/assets/js/5c838b7d.abeb9ef9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2242],{4394:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var t=r(5893),s=r(1151);const o={title:"Customization"},i=void 0,a={id:"customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.3.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/customization",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/metrics"}},c={},l=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"kubectl edit configmap --namespace eraser-system eraser-manager-config\n"})}),"\n",(0,t.jsx)(n.p,{children:"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."}),"\n",(0,t.jsx)(n.h2,{id:"key-concepts",children:"Key Concepts"}),"\n",(0,t.jsx)(n.h3,{id:"basic-architecture",children:"Basic architecture"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.em,{children:"manager"})," runs as a pod in your cluster and manages ",(0,t.jsx)(n.em,{children:"ImageJobs"}),". Think of\nan ",(0,t.jsx)(n.em,{children:"ImageJob"})," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,t.jsx)(n.em,{children:"ImageJob"})," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Assessment"}),"\n",(0,t.jsx)(n.li,{children:"Removal."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"scheduling",children:"Scheduling"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," can either be created on-demand (see ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/manual-removal",children:"Manual Removal"}),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."]}),"\n",(0,t.jsx)(n.h3,{id:"fault-tolerance",children:"Fault Tolerance"}),"\n",(0,t.jsxs)(n.p,{children:["Because an ",(0,t.jsx)(n.em,{children:"ImageJob"})," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,t.jsx)(n.code,{children:"manager.imageJob.successRatio"})," property to\n",(0,t.jsx)(n.code,{children:"1.0"}),". If 75% success sounds good to you, set it to ",(0,t.jsx)(n.code,{children:"0.75"}),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,t.jsx)(n.em,{children:"ImageJob"})," report success, the job as\na whole will be marked as a failure."]}),"\n",(0,t.jsxs)(n.p,{children:["This is mainly to help diagnose error conditions. As such, you can set\n",(0,t.jsx)(n.code,{children:"manager.imageJob.cleanup.delayOnFailure"})," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."]}),"\n",(0,t.jsx)(n.h3,{id:"excluding-nodes",children:"Excluding Nodes"}),"\n",(0,t.jsxs)(n.p,{children:["For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,t.jsx)(n.code,{children:"eraser.sh/cleanup.filter"}),", but you can configure the behavior with\nthe options under ",(0,t.jsx)(n.code,{children:"manager.nodeFilter"}),". The ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"})," provides more detail."]}),"\n",(0,t.jsx)(n.h3,{id:"configuring-components",children:"Configuring Components"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Collection (What is on the node?)"}),"\n",(0,t.jsx)(n.li,{children:"Scanning (What images conform to the policy I've provided?)"}),"\n",(0,t.jsx)(n.li,{children:"Removal (Remove images based on the results of the above)"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,t.jsx)(n.em,{children:"ImageJobs"})," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["The collector and/or scanner ",(0,t.jsx)(n.code,{children:"components"})," are enabled, AND"]}),"\n",(0,t.jsxs)(n.li,{children:["The job was ",(0,t.jsx)(n.em,{children:"not"})," triggered manually by creating an ",(0,t.jsx)(n.em,{children:"ImageList"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"swapping-out-components",children:"Swapping out components"}),"\n",(0,t.jsxs)(n.p,{children:["The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,t.jsx)(n.code,{children:"components.<component>.image.repo"})," and ",(0,t.jsx)(n.code,{children:"components.<component>.image.tag"}),",\nwhere ",(0,t.jsx)(n.code,{children:"<component>"})," is one of ",(0,t.jsx)(n.code,{children:"collector"}),", ",(0,t.jsx)(n.code,{children:"scanner"}),", or ",(0,t.jsx)(n.code,{children:"remover"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"universal-options",children:"Universal Options"}),"\n",(0,t.jsxs)(n.p,{children:["The following portions of the configmap apply no matter how you spawn your\n",(0,t.jsx)(n.em,{children:"ImageJob"}),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'manager:\n runtime:\n name: containerd\n address: unix:///run/containerd/containerd.sock\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n'})}),"\n",(0,t.jsx)(n.h2,{id:"component-options",children:"Component Options"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n"})}),"\n",(0,t.jsx)(n.h2,{id:"scanner-options",children:"Scanner Options"}),"\n",(0,t.jsxs)(n.p,{children:["These options can be provided to ",(0,t.jsx)(n.code,{children:"components.scanner.config"}),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."]}),"\n",(0,t.jsxs)(n.p,{children:["Below are the values recognized by the provided ",(0,t.jsx)(n.code,{children:"eraser-trivy-scanner"})," image.\nValues provided below are the defaults."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more information\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\n ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n"})}),"\n",(0,t.jsx)(n.h2,{id:"detailed-options",children:"Detailed Options"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Option"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Default"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.runtime.name"}),(0,t.jsx)(n.td,{children:"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."}),(0,t.jsx)(n.td,{children:"containerd"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.runtime.address"}),(0,t.jsx)(n.td,{children:"The runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions."}),(0,t.jsx)(n.td,{children:"unix:///run/containerd/containerd.sock"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.otlpEndpoint"}),(0,t.jsx)(n.td,{children:"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.logLevel"}),(0,t.jsx)(n.td,{children:"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."}),(0,t.jsx)(n.td,{children:"info"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.repeatInterval"}),(0,t.jsxs)(n.td,{children:["Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,t.jsx)(n.em,{children:"ImageJob"})," at the interval provided."]}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.beginImmediately"}),(0,t.jsxs)(n.td,{children:["If set to true, the fist ",(0,t.jsx)(n.em,{children:"ImageJob"})," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."]}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.enabled"}),(0,t.jsxs)(n.td,{children:["Whether to enable profiling for the manager's containers. This is for debugging with ",(0,t.jsx)(n.code,{children:"go tool pprof"}),"."]}),(0,t.jsx)(n.td,{children:"false"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.port"}),(0,t.jsx)(n.td,{children:"The port on which to expose the profiling endpoint."}),(0,t.jsx)(n.td,{children:"6060"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.successRatio"}),(0,t.jsx)(n.td,{children:"The ratio of successful image jobs required before a cleanup is performed."}),(0,t.jsx)(n.td,{children:"1.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnSuccess"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a successful image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"0s"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnFailure"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a failed image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.pullSecrets"}),(0,t.jsx)(n.td,{children:"The image pull secrets to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.priorityClassName"}),(0,t.jsx)(n.td,{children:"The priority class to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.type"}),(0,t.jsx)(n.td,{children:'The type of node filter to use. Must be either "exclude" or "include".'}),(0,t.jsx)(n.td,{children:"exclude"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.selectors"}),(0,t.jsx)(n.td,{children:"A list of selectors used to filter nodes."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the collector component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the collector image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/collector"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the collector image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the collector container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the collector container."}),(0,t.jsx)(n.td,{children:"7m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the scanner component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the scanner image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the scanner image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the scanner container."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the scanner container."}),(0,t.jsx)(n.td,{children:"1000m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"2Gi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.config"}),(0,t.jsx)(n.td,{children:"The configuration to pass to the scanner container, as a YAML string."}),(0,t.jsx)(n.td,{children:"See YAML below"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the remover image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/remover"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the remover image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the remover container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the remover container."}),(0,t.jsx)(n.td,{children:"0"})]})]})]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>i});var t=r(7294);const s={},o=t.createContext(s);function i(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/5e95c892.b00730d7.js b/docs/assets/js/5e95c892.b00730d7.js new file mode 100644 index 0000000000..763248f82e --- /dev/null +++ b/docs/assets/js/5e95c892.b00730d7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9661],{1892:(e,s,r)=>{r.r(s),r.d(s,{default:()=>l});r(7294);var t=r(512),u=r(833),a=r(5281),c=r(8790),n=r(7372),i=r(5893);function l(e){return(0,i.jsx)(u.FG,{className:(0,t.Z)(a.k.wrapper.docsPages),children:(0,i.jsx)(n.Z,{children:(0,c.H)(e.route.routes)})})}}}]); \ No newline at end of file diff --git a/docs/assets/js/62c6dc45.beacabe7.js b/docs/assets/js/62c6dc45.beacabe7.js new file mode 100644 index 0000000000..b5e7d58b37 --- /dev/null +++ b/docs/assets/js/62c6dc45.beacabe7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6252],{5979:(e,s,i)=>{i.r(s),i.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var r=i(5893),n=i(1151);const t={title:"Exclusion"},o=void 0,a={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.0.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v1.0.x/exclusion",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v1.0.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v1.0.x/customization"}},c={},l=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function d(e){const s={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,n.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,r.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,r.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,r.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,r.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,r.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,r.jsxs)(s.p,{children:["Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,r.jsx)(s.code,{children:"include"})," or ",(0,r.jsx)(s.code,{children:"exclude"})," from the cleanup process using the configmap. For more information, see the section on ",(0,r.jsx)(s.a,{href:"https://eraser-dev.github.io/eraser/docs/customization",children:"customization"}),"."]})]})}function u(e={}){const{wrapper:s}={...(0,n.a)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,s,i)=>{i.d(s,{Z:()=>a,a:()=>o});var r=i(7294);const n={},t=r.createContext(n);function o(e){const s=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/62c6dc45.d4fbe534.js b/docs/assets/js/62c6dc45.d4fbe534.js deleted file mode 100644 index d082d2fe55..0000000000 --- a/docs/assets/js/62c6dc45.d4fbe534.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6252],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?o(Object(t),!0).forEach((function(r){i(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):o(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function s(e,r){if(null==e)return{};var t,n,i=function(e,r){if(null==e)return{};var t,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)t=o[n],r.indexOf(t)>=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)t=o[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=n.createContext({}),c=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},p=function(e){var r=c(e.components);return n.createElement(l.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(t),m=i,f=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?n.createElement(f,a(a({ref:r},p),{},{components:t})):n.createElement(f,a({ref:r},p))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var s={};for(var l in r)hasOwnProperty.call(r,l)&&(s[l]=r[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var c=2;c<o;c++)a[c]=t[c];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}d.displayName="MDXCreateElement"},6634:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var n=t(7462),i=(t(7294),t(3905));const o={title:"Exclusion"},a=void 0,s={unversionedId:"exclusion",id:"version-v1.0.x/exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.0.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v1.0.x/exclusion",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v1.0.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v1.0.x/customization"}},l={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],p={toc:c};function u(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the configmap. For more information, see the section on ",(0,i.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization"},"customization"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/6739d7ff.89c2e76b.js b/docs/assets/js/6739d7ff.89c2e76b.js deleted file mode 100644 index 1d48df071d..0000000000 --- a/docs/assets/js/6739d7ff.89c2e76b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5384],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,i(i({ref:t},p),{},{components:r})):n.createElement(d,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<o;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},5088:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},i=void 0,l={unversionedId:"installation",id:"version-v1.2.x/installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.2.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v1.2.x/installation",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v1.2.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v1.2.x/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.2.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/6739d7ff.c14998ff.js b/docs/assets/js/6739d7ff.c14998ff.js new file mode 100644 index 0000000000..8fa66cbea9 --- /dev/null +++ b/docs/assets/js/6739d7ff.c14998ff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5384],{6160:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var s=n(5893),r=n(1151);const a={title:"Installation"},i=void 0,o={id:"installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.2.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v1.2.x/installation",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v1.2.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v1.2.x/quick-start"}},l={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.2.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>i});var s=n(7294);const r={},a=s.createContext(r);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/6780.2f5c1e5a.js b/docs/assets/js/6780.2f5c1e5a.js deleted file mode 100644 index 7939a000c1..0000000000 --- a/docs/assets/js/6780.2f5c1e5a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6780],{6780:(e,t,r)=>{function n(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t,r){var a,c=t.initialState;return{getState:function(){return c},dispatch:function(a,i){var l=function(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?n(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):n(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}({},c);c=e(c,{type:a,props:t,payload:i}),r({state:c,prevState:l})},pendingRequests:(a=[],{add:function(e){return a.push(e),e.finally((function(){a=a.filter((function(t){return t!==e}))}))},cancelAll:function(){a.forEach((function(e){return e.cancel()}))},isEmpty:function(){return 0===a.length}})}}function c(e){return e.reduce((function(e,t){return e.concat(t)}),[])}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){u(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function u(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e){return 0===e.collections.length?0:e.collections.reduce((function(e,t){return e+t.items.length}),0)}r.r(t),r.d(t,{DocSearchModal:()=>Dr});var f=0;var m=function(){};function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function d(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function h(e,t){var r=[];return Promise.resolve(e(t)).then((function(e){return Array.isArray(e),Promise.all(e.filter((function(e){return Boolean(e)})).map((function(e){if(e.sourceId,r.includes(e.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(e.sourceId)," is not unique."));r.push(e.sourceId);var t=function(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?p(Object(r),!0).forEach((function(t){d(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):p(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}({getItemInputValue:function(e){return e.state.query},getItemUrl:function(){},onSelect:function(e){(0,e.setIsOpen)(!1)},onActive:m},e);return Promise.resolve(t)})))}))}function v(e){return function(e){if(Array.isArray(e))return y(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return y(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return y(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function y(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function g(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function b(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?g(Object(r),!0).forEach((function(t){O(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):g(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function O(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function S(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function j(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?S(Object(r),!0).forEach((function(t){E(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):S(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function E(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function w(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function P(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?w(Object(r),!0).forEach((function(t){I(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):w(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function I(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function D(e){return function(e){if(Array.isArray(e))return C(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return C(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return C(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function C(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function k(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function A(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?k(Object(r),!0).forEach((function(t){x(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):k(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function x(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function N(e){return Boolean(e.execute)}function R(e,t){return r=e,Boolean(null==r?void 0:r.execute)?A(A({},e),{},{requests:e.queries.map((function(r){return{query:r,sourceId:t,transformResponse:e.transformResponse}}))}):{items:e,sourceId:t};var r}function q(e){var t=e.reduce((function(e,t){if(!N(t))return e.push(t),e;var r=t.searchClient,n=t.execute,o=t.requesterId,a=t.requests,c=e.find((function(e){return N(t)&&N(e)&&e.searchClient===r&&Boolean(o)&&e.requesterId===o}));if(c){var i;(i=c.items).push.apply(i,D(a))}else{var l={execute:n,requesterId:o,items:a,searchClient:r};e.push(l)}return e}),[]).map((function(e){if(!N(e))return Promise.resolve(e);var t=e,r=t.execute,n=t.items;return r({searchClient:t.searchClient,requests:n})}));return Promise.all(t).then((function(e){return c(e)}))}function _(e,t){return t.map((function(t){var r=e.filter((function(e){return e.sourceId===t.sourceId})),n=r.map((function(e){return e.items})),o=r[0].transformResponse,a=o?o(function(e){var t=e.map((function(e){var t;return P(P({},e),{},{hits:null===(t=e.hits)||void 0===t?void 0:t.map((function(t){return P(P({},t),{},{__autocomplete_indexName:e.index,__autocomplete_queryID:e.queryID})}))})}));return{results:t,hits:t.map((function(e){return e.hits})).filter(Boolean),facetHits:t.map((function(e){var t;return null===(t=e.facetHits)||void 0===t?void 0:t.map((function(e){return{label:e.value,count:e.count,_highlightResult:{label:{value:e.highlighted}}}}))})).filter(Boolean)}}(n)):n;return Array.isArray(a),a.every(Boolean),'The `getItems` function from source "'.concat(t.sourceId,'" must return an array of items but returned ').concat(JSON.stringify(void 0),".\n\nDid you forget to return items?\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems"),{source:t,items:a}}))}function T(e,t){var r=t;return{then:function(t,n){return T(e.then(H(t,r,e),H(n,r,e)),r)},catch:function(t){return T(e.catch(H(t,r,e)),r)},finally:function(t){return t&&r.onCancelList.push(t),T(e.finally(H(t&&function(){return r.onCancelList=[],t()},r,e)),r)},cancel:function(){r.isCanceled=!0;var e=r.onCancelList;r.onCancelList=[],e.forEach((function(e){e()}))},isCanceled:function(){return!0===r.isCanceled}}}function L(e){return T(new Promise((function(t,r){return e(t,r)})),{isCanceled:!1,onCancelList:[]})}function M(e){return T(e,{isCanceled:!1,onCancelList:[]})}function H(e,t,r){return e?function(r){return t.isCanceled?r:e(r)}:r}function F(e){var t=function(e){var t=e.collections.map((function(e){return e.items.length})).reduce((function(e,t,r){var n=(e[r-1]||0)+t;return e.push(n),e}),[]).reduce((function(t,r){return r<=e.activeItemId?t+1:t}),0);return e.collections[t]}(e);if(!t)return null;var r=t.items[function(e){for(var t=e.state,r=e.collection,n=!1,o=0,a=0;!1===n;){var c=t.collections[o];if(c===r){n=!0;break}a+=c.items.length,o++}return t.activeItemId-a}({state:e,collection:t})],n=t.source;return{item:r,itemInputValue:n.getItemInputValue({item:r,state:e}),itemUrl:n.getItemUrl({item:r,state:e}),source:n}}L.resolve=function(e){return M(Promise.resolve(e))},L.reject=function(e){return M(Promise.reject(e))};var U=["event","nextState","props","query","refresh","store"];function B(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function V(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?B(Object(r),!0).forEach((function(t){z(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):B(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function z(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function K(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var J,$,W,Q=null,Y=(J=-1,$=-1,W=void 0,function(e){var t=++J;return Promise.resolve(e).then((function(e){return W&&t<$?W:($=t,W=e,e)}))});function G(e){var t=e.event,r=e.nextState,n=void 0===r?{}:r,o=e.props,a=e.query,i=e.refresh,l=e.store,u=K(e,U);Q&&o.environment.clearTimeout(Q);var s=u.setCollections,f=u.setIsOpen,m=u.setQuery,p=u.setActiveItemId,d=u.setStatus;if(m(a),p(o.defaultActiveItemId),!a&&!1===o.openOnFocus){var h,v=l.getState().collections.map((function(e){return V(V({},e),{},{items:[]})}));d("idle"),s(v),f(null!==(h=n.isOpen)&&void 0!==h?h:o.shouldPanelOpen({state:l.getState()}));var y=M(Y(v).then((function(){return Promise.resolve()})));return l.pendingRequests.add(y)}d("loading"),Q=o.environment.setTimeout((function(){d("stalled")}),o.stallThreshold);var g=M(Y(o.getSources(V({query:a,refresh:i,state:l.getState()},u)).then((function(e){return Promise.all(e.map((function(e){return Promise.resolve(e.getItems(V({query:a,refresh:i,state:l.getState()},u))).then((function(t){return R(t,e.sourceId)}))}))).then(q).then((function(t){return _(t,e)})).then((function(e){return function(e){var t=e.collections,r=e.props,n=e.state,o=t.reduce((function(e,t){return j(j({},e),{},E({},t.source.sourceId,j(j({},t.source),{},{getItems:function(){return c(t.items)}})))}),{});return c(r.reshape({sources:Object.values(o),sourcesBySourceId:o,state:n})).filter(Boolean).map((function(e){return{source:e,items:e.getItems()}}))}({collections:e,props:o,state:l.getState()})}))})))).then((function(e){var r;d("idle"),s(e);var c=o.shouldPanelOpen({state:l.getState()});f(null!==(r=n.isOpen)&&void 0!==r?r:o.openOnFocus&&!a&&c||c);var m=F(l.getState());if(null!==l.getState().activeItemId&&m){var p=m.item,h=m.itemInputValue,v=m.itemUrl,y=m.source;y.onActive(V({event:t,item:p,itemInputValue:h,itemUrl:v,refresh:i,source:y,state:l.getState()},u))}})).finally((function(){d("idle"),Q&&o.environment.clearTimeout(Q)}));return l.pendingRequests.add(g)}var X=["event","props","refresh","store"];function Z(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function ee(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?Z(Object(r),!0).forEach((function(t){te(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):Z(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function te(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function re(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var ne=/((gt|sm)-|galaxy nexus)|samsung[- ]/i;var oe=["props","refresh","store"],ae=["inputElement","formElement","panelElement"],ce=["inputElement"],ie=["inputElement","maxLength"],le=["item","source"];function ue(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function se(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?ue(Object(r),!0).forEach((function(t){fe(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):ue(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function fe(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function me(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function pe(e){var t=e.props,r=e.refresh,n=e.store,o=me(e,oe);return{getEnvironmentProps:function(e){var r=e.inputElement,o=e.formElement,a=e.panelElement;function c(e){!n.getState().isOpen&&n.pendingRequests.isEmpty()||e.target===r||!1===[o,a].some((function(t){return r=t,n=e.target,r===n||r.contains(n);var r,n}))&&(n.dispatch("blur",null),t.debug||n.pendingRequests.cancelAll())}return se({onTouchStart:c,onMouseDown:c,onTouchMove:function(e){!1!==n.getState().isOpen&&r===t.environment.document.activeElement&&e.target!==r&&r.blur()}},me(e,ae))},getRootProps:function(e){return se({role:"combobox","aria-expanded":n.getState().isOpen,"aria-haspopup":"listbox","aria-owns":n.getState().isOpen?"".concat(t.id,"-list"):void 0,"aria-labelledby":"".concat(t.id,"-label")},e)},getFormProps:function(e){e.inputElement;return se({action:"",noValidate:!0,role:"search",onSubmit:function(a){var c;a.preventDefault(),t.onSubmit(se({event:a,refresh:r,state:n.getState()},o)),n.dispatch("submit",null),null===(c=e.inputElement)||void 0===c||c.blur()},onReset:function(a){var c;a.preventDefault(),t.onReset(se({event:a,refresh:r,state:n.getState()},o)),n.dispatch("reset",null),null===(c=e.inputElement)||void 0===c||c.focus()}},me(e,ce))},getLabelProps:function(e){return se({htmlFor:"".concat(t.id,"-input"),id:"".concat(t.id,"-label")},e)},getInputProps:function(e){var a;function c(e){(t.openOnFocus||Boolean(n.getState().query))&&G(se({event:e,props:t,query:n.getState().completion||n.getState().query,refresh:r,store:n},o)),n.dispatch("focus",null)}var i=e||{},l=(i.inputElement,i.maxLength),u=void 0===l?512:l,s=me(i,ie),f=F(n.getState()),p=function(e){return Boolean(e&&e.match(ne))}((null===(a=t.environment.navigator)||void 0===a?void 0:a.userAgent)||""),d=null!=f&&f.itemUrl&&!p?"go":"search";return se({"aria-autocomplete":"both","aria-activedescendant":n.getState().isOpen&&null!==n.getState().activeItemId?"".concat(t.id,"-item-").concat(n.getState().activeItemId):void 0,"aria-controls":n.getState().isOpen?"".concat(t.id,"-list"):void 0,"aria-labelledby":"".concat(t.id,"-label"),value:n.getState().completion||n.getState().query,id:"".concat(t.id,"-input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:d,spellCheck:"false",autoFocus:t.autoFocus,placeholder:t.placeholder,maxLength:u,type:"search",onChange:function(e){G(se({event:e,props:t,query:e.currentTarget.value.slice(0,u),refresh:r,store:n},o))},onKeyDown:function(e){!function(e){var t=e.event,r=e.props,n=e.refresh,o=e.store,a=re(e,X);if("ArrowUp"===t.key||"ArrowDown"===t.key){var c=function(){var e=r.environment.document.getElementById("".concat(r.id,"-item-").concat(o.getState().activeItemId));e&&(e.scrollIntoViewIfNeeded?e.scrollIntoViewIfNeeded(!1):e.scrollIntoView(!1))},i=function(){var e=F(o.getState());if(null!==o.getState().activeItemId&&e){var r=e.item,c=e.itemInputValue,i=e.itemUrl,l=e.source;l.onActive(ee({event:t,item:r,itemInputValue:c,itemUrl:i,refresh:n,source:l,state:o.getState()},a))}};t.preventDefault(),!1===o.getState().isOpen&&(r.openOnFocus||Boolean(o.getState().query))?G(ee({event:t,props:r,query:o.getState().query,refresh:n,store:o},a)).then((function(){o.dispatch(t.key,{nextActiveItemId:r.defaultActiveItemId}),i(),setTimeout(c,0)})):(o.dispatch(t.key,{}),i(),c())}else if("Escape"===t.key)t.preventDefault(),o.dispatch(t.key,null),o.pendingRequests.cancelAll();else if("Tab"===t.key)o.dispatch("blur",null),o.pendingRequests.cancelAll();else if("Enter"===t.key){if(null===o.getState().activeItemId||o.getState().collections.every((function(e){return 0===e.items.length})))return void(r.debug||o.pendingRequests.cancelAll());t.preventDefault();var l=F(o.getState()),u=l.item,s=l.itemInputValue,f=l.itemUrl,m=l.source;if(t.metaKey||t.ctrlKey)void 0!==f&&(m.onSelect(ee({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},a)),r.navigator.navigateNewTab({itemUrl:f,item:u,state:o.getState()}));else if(t.shiftKey)void 0!==f&&(m.onSelect(ee({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},a)),r.navigator.navigateNewWindow({itemUrl:f,item:u,state:o.getState()}));else if(t.altKey);else{if(void 0!==f)return m.onSelect(ee({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},a)),void r.navigator.navigate({itemUrl:f,item:u,state:o.getState()});G(ee({event:t,nextState:{isOpen:!1},props:r,query:s,refresh:n,store:o},a)).then((function(){m.onSelect(ee({event:t,item:u,itemInputValue:s,itemUrl:f,refresh:n,source:m,state:o.getState()},a))}))}}}(se({event:e,props:t,refresh:r,store:n},o))},onFocus:c,onBlur:m,onClick:function(r){e.inputElement!==t.environment.document.activeElement||n.getState().isOpen||c(r)}},s)},getPanelProps:function(e){return se({onMouseDown:function(e){e.preventDefault()},onMouseLeave:function(){n.dispatch("mouseleave",null)}},e)},getListProps:function(e){return se({role:"listbox","aria-labelledby":"".concat(t.id,"-label"),id:"".concat(t.id,"-list")},e)},getItemProps:function(e){var a=e.item,c=e.source,i=me(e,le);return se({id:"".concat(t.id,"-item-").concat(a.__autocomplete_id),role:"option","aria-selected":n.getState().activeItemId===a.__autocomplete_id,onMouseMove:function(e){if(a.__autocomplete_id!==n.getState().activeItemId){n.dispatch("mousemove",a.__autocomplete_id);var t=F(n.getState());if(null!==n.getState().activeItemId&&t){var c=t.item,i=t.itemInputValue,l=t.itemUrl,u=t.source;u.onActive(se({event:e,item:c,itemInputValue:i,itemUrl:l,refresh:r,source:u,state:n.getState()},o))}}},onMouseDown:function(e){e.preventDefault()},onClick:function(e){var i=c.getItemInputValue({item:a,state:n.getState()}),l=c.getItemUrl({item:a,state:n.getState()});(l?Promise.resolve():G(se({event:e,nextState:{isOpen:!1},props:t,query:i,refresh:r,store:n},o))).then((function(){c.onSelect(se({event:e,item:a,itemInputValue:i,itemUrl:l,refresh:r,source:c,state:n.getState()},o))}))}},i)}}}var de=[{segment:"autocomplete-core",version:"1.7.1"}];function he(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function ve(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?he(Object(r),!0).forEach((function(t){ye(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):he(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function ye(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function ge(e){var t,r,n,o,a=e.plugins,c=e.options,i=null===(t=((null===(r=c.__autocomplete_metadata)||void 0===r?void 0:r.userAgents)||[])[0])||void 0===t?void 0:t.segment,l=i?ye({},i,Object.keys((null===(n=c.__autocomplete_metadata)||void 0===n?void 0:n.options)||{})):{};return{plugins:a.map((function(e){return{name:e.name,options:Object.keys(e.__autocomplete_pluginOptions||[])}})),options:ve({"autocomplete-core":Object.keys(c)},l),ua:de.concat((null===(o=c.__autocomplete_metadata)||void 0===o?void 0:o.userAgents)||[])}}function be(e){var t,r=e.state;return!1===r.isOpen||null===r.activeItemId?null:(null===(t=F(r))||void 0===t?void 0:t.itemInputValue)||null}function Oe(e,t,r,n){if(!r)return null;if(e<0&&(null===t||null!==n&&0===t))return r+e;var o=(null===t?-1:t)+e;return o<=-1||o>=r?null===n?null:0:o}function Se(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function je(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?Se(Object(r),!0).forEach((function(t){Ee(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):Se(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function Ee(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var we=function(e,t){switch(t.type){case"setActiveItemId":case"mousemove":return je(je({},e),{},{activeItemId:t.payload});case"setQuery":return je(je({},e),{},{query:t.payload,completion:null});case"setCollections":return je(je({},e),{},{collections:t.payload});case"setIsOpen":return je(je({},e),{},{isOpen:t.payload});case"setStatus":return je(je({},e),{},{status:t.payload});case"setContext":return je(je({},e),{},{context:je(je({},e.context),t.payload)});case"ArrowDown":var r=je(je({},e),{},{activeItemId:t.payload.hasOwnProperty("nextActiveItemId")?t.payload.nextActiveItemId:Oe(1,e.activeItemId,s(e),t.props.defaultActiveItemId)});return je(je({},r),{},{completion:be({state:r})});case"ArrowUp":var n=je(je({},e),{},{activeItemId:Oe(-1,e.activeItemId,s(e),t.props.defaultActiveItemId)});return je(je({},n),{},{completion:be({state:n})});case"Escape":return e.isOpen?je(je({},e),{},{activeItemId:null,isOpen:!1,completion:null}):je(je({},e),{},{activeItemId:null,query:"",status:"idle",collections:[]});case"submit":return je(je({},e),{},{activeItemId:null,isOpen:!1,status:"idle"});case"reset":return je(je({},e),{},{activeItemId:!0===t.props.openOnFocus?t.props.defaultActiveItemId:null,status:"idle",query:""});case"focus":return je(je({},e),{},{activeItemId:t.props.defaultActiveItemId,isOpen:(t.props.openOnFocus||Boolean(e.query))&&t.props.shouldPanelOpen({state:e})});case"blur":return t.props.debug?e:je(je({},e),{},{isOpen:!1,activeItemId:null});case"mouseleave":return je(je({},e),{},{activeItemId:t.props.defaultActiveItemId});default:return"The reducer action ".concat(JSON.stringify(t.type)," is not supported."),e}};function Pe(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function Ie(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?Pe(Object(r),!0).forEach((function(t){De(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):Pe(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function De(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function Ce(e){var t=[],r=function(e,t){var r,n="undefined"!=typeof window?window:{},o=e.plugins||[];return b(b({debug:!1,openOnFocus:!1,placeholder:"",autoFocus:!1,defaultActiveItemId:null,stallThreshold:300,environment:n,shouldPanelOpen:function(e){return s(e.state)>0},reshape:function(e){return e.sources}},e),{},{id:null!==(r=e.id)&&void 0!==r?r:"autocomplete-".concat(f++),plugins:o,initialState:b({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},e.initialState),onStateChange:function(t){var r;null===(r=e.onStateChange)||void 0===r||r.call(e,t),o.forEach((function(e){var r;return null===(r=e.onStateChange)||void 0===r?void 0:r.call(e,t)}))},onSubmit:function(t){var r;null===(r=e.onSubmit)||void 0===r||r.call(e,t),o.forEach((function(e){var r;return null===(r=e.onSubmit)||void 0===r?void 0:r.call(e,t)}))},onReset:function(t){var r;null===(r=e.onReset)||void 0===r||r.call(e,t),o.forEach((function(e){var r;return null===(r=e.onReset)||void 0===r?void 0:r.call(e,t)}))},getSources:function(r){return Promise.all([].concat(v(o.map((function(e){return e.getSources}))),[e.getSources]).filter(Boolean).map((function(e){return h(e,r)}))).then((function(e){return c(e)})).then((function(e){return e.map((function(e){return b(b({},e),{},{onSelect:function(r){e.onSelect(r),t.forEach((function(e){var t;return null===(t=e.onSelect)||void 0===t?void 0:t.call(e,r)}))},onActive:function(r){e.onActive(r),t.forEach((function(e){var t;return null===(t=e.onActive)||void 0===t?void 0:t.call(e,r)}))}})}))}))},navigator:b({navigate:function(e){var t=e.itemUrl;n.location.assign(t)},navigateNewTab:function(e){var t=e.itemUrl,r=n.open(t,"_blank","noopener");null==r||r.focus()},navigateNewWindow:function(e){var t=e.itemUrl;n.open(t,"_blank","noopener")}},e.navigator)})}(e,t),n=a(we,r,(function(e){var t=e.prevState,n=e.state;r.onStateChange(Ie({prevState:t,state:n,refresh:u},o))})),o=function(e){var t=e.store;return{setActiveItemId:function(e){t.dispatch("setActiveItemId",e)},setQuery:function(e){t.dispatch("setQuery",e)},setCollections:function(e){var r=0,n=e.map((function(e){return l(l({},e),{},{items:c(e.items).map((function(e){return l(l({},e),{},{__autocomplete_id:r++})}))})}));t.dispatch("setCollections",n)},setIsOpen:function(e){t.dispatch("setIsOpen",e)},setStatus:function(e){t.dispatch("setStatus",e)},setContext:function(e){t.dispatch("setContext",e)}}}({store:n}),i=pe(Ie({props:r,refresh:u,store:n},o));function u(){return G(Ie({event:new Event("input"),nextState:{isOpen:n.getState().isOpen},props:r,query:n.getState().query,refresh:u,store:n},o))}return r.plugins.forEach((function(e){var r;return null===(r=e.subscribe)||void 0===r?void 0:r.call(e,Ie(Ie({},o),{},{refresh:u,onSelect:function(e){t.push({onSelect:e})},onActive:function(e){t.push({onActive:e})}}))})),function(e){var t,r,n=e.metadata,o=e.environment;if(null===(t=o.navigator)||void 0===t||null===(r=t.userAgent)||void 0===r?void 0:r.includes("Algolia Crawler")){var a=o.document.createElement("meta"),c=o.document.querySelector("head");a.name="algolia:metadata",setTimeout((function(){a.content=JSON.stringify(n),c.appendChild(a)}),0)}}({metadata:ge({plugins:r.plugins,options:e}),environment:r.environment}),Ie(Ie({refresh:u},i),o)}var ke=r(7294);function Ae(e){var t=e.translations,r=(void 0===t?{}:t).searchByText,n=void 0===r?"Search by":r;return ke.createElement("a",{href:"https://www.algolia.com/ref/docsearch/?utm_source=".concat(window.location.hostname,"&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch"),target:"_blank",rel:"noopener noreferrer"},ke.createElement("span",{className:"DocSearch-Label"},n),ke.createElement("svg",{width:"77",height:"19","aria-label":"Algolia",role:"img"},ke.createElement("path",{d:"M2.5067 0h14.0245c1.384.001 2.5058 1.1205 2.5068 2.5017V16.5c-.0014 1.3808-1.1232 2.4995-2.5068 2.5H2.5067C1.1232 18.9995.0014 17.8808 0 16.5V2.4958A2.495 2.495 0 01.735.7294 2.505 2.505 0 012.5068 0zM37.95 15.0695c-3.7068.0168-3.7068-2.986-3.7068-3.4634L34.2372.3576 36.498 0v11.1794c0 .2715 0 1.9889 1.452 1.994v1.8961zm-9.1666-1.8388c.694 0 1.2086-.0397 1.5678-.1088v-2.2934a5.3639 5.3639 0 00-1.3303-.1679 4.8283 4.8283 0 00-.758.0582 2.2845 2.2845 0 00-.688.2024c-.2029.0979-.371.2362-.4919.4142-.1268.1788-.185.2826-.185.5533 0 .5297.185.8359.5205 1.0375.3355.2016.7928.3053 1.365.3053v-.0008zm-.1969-8.1817c.7463 0 1.3768.092 1.8856.2767.5088.1838.9195.4428 1.2204.7717.3068.334.5147.7777.6423 1.251.1327.4723.196.991.196 1.5603v5.798c-.5235.1036-1.05.192-1.5787.2649-.7048.1037-1.4976.156-2.3774.156-.5832 0-1.1215-.0582-1.6016-.167a3.385 3.385 0 01-1.2432-.5364 2.6034 2.6034 0 01-.8037-.9565c-.191-.3922-.29-.9447-.29-1.5208 0-.5533.11-.905.3246-1.2863a2.7351 2.7351 0 01.8849-.9329c.376-.242.8029-.415 1.2948-.5187a7.4517 7.4517 0 011.5381-.156 7.1162 7.1162 0 011.6667.2024V8.886c0-.259-.0296-.5061-.093-.7372a1.5847 1.5847 0 00-.3245-.6158 1.5079 1.5079 0 00-.6119-.4158 2.6788 2.6788 0 00-.966-.173c-.5206 0-.9948.0634-1.4283.1384a6.5481 6.5481 0 00-1.065.259l-.2712-1.849c.2831-.0986.7048-.1964 1.2491-.2943a9.2979 9.2979 0 011.752-.1501v.0008zm44.6597 8.1193c.6947 0 1.2086-.0405 1.567-.1097v-2.2942a5.3743 5.3743 0 00-1.3303-.1679c-.2485 0-.503.0177-.7573.0582a2.2853 2.2853 0 00-.688.2024 1.2333 1.2333 0 00-.4918.4142c-.1268.1788-.1843.2826-.1843.5533 0 .5297.1843.8359.5198 1.0375.3414.2066.7927.3053 1.365.3053v.0009zm-.191-8.1767c.7463 0 1.3768.0912 1.8856.2759.5087.1847.9195.4436 1.2204.7717.3.329.5147.7786.6414 1.251a5.7248 5.7248 0 01.197 1.562v5.7972c-.3466.0742-.874.1602-1.5788.2648-.7049.1038-1.4976.1552-2.3774.1552-.5832 0-1.1215-.0573-1.6016-.167a3.385 3.385 0 01-1.2432-.5356 2.6034 2.6034 0 01-.8038-.9565c-.191-.3922-.2898-.9447-.2898-1.5216 0-.5533.1098-.905.3245-1.2854a2.7373 2.7373 0 01.8849-.9338c.376-.2412.8029-.4141 1.2947-.5178a7.4545 7.4545 0 012.325-.1097c.2781.0287.5672.081.879.156v-.3686a2.7781 2.7781 0 00-.092-.738 1.5788 1.5788 0 00-.3246-.6166 1.5079 1.5079 0 00-.612-.415 2.6797 2.6797 0 00-.966-.1729c-.5205 0-.9947.0633-1.4282.1384a6.5608 6.5608 0 00-1.065.259l-.2712-1.8498c.283-.0979.7048-.1957 1.2491-.2935a9.8597 9.8597 0 011.752-.1494zm-6.79-1.072c-.7576.001-1.373-.6103-1.3759-1.3664 0-.755.6128-1.3664 1.376-1.3664.764 0 1.3775.6115 1.3775 1.3664s-.6195 1.3664-1.3776 1.3664zm1.1393 11.1507h-2.2726V5.3409l2.2734-.3568v10.0845l-.0008.0017zm-3.984 0c-3.707.0168-3.707-2.986-3.707-3.4642L59.7069.3576 61.9685 0v11.1794c0 .2715 0 1.9889 1.452 1.994V15.0703zm-7.3512-4.979c0-.975-.2138-1.7873-.6305-2.3516-.4167-.571-.9998-.852-1.747-.852-.7454 0-1.3302.281-1.7452.852-.4166.5702-.6195 1.3765-.6195 2.3516 0 .9851.208 1.6473.6254 2.2183.4158.576.9998.8587 1.7461.8587.7454 0 1.3303-.2885 1.747-.8595.4158-.5761.6237-1.2315.6237-2.2184v.0009zm2.3132-.006c0 .7609-.1099 1.3361-.3356 1.9654a4.654 4.654 0 01-.9533 1.6076A4.214 4.214 0 0155.613 14.69c-.579.2412-1.4697.3795-1.9143.3795-.4462-.005-1.3303-.1324-1.9033-.3795a4.307 4.307 0 01-1.474-1.0316c-.4115-.4445-.7293-.9801-.9609-1.6076a5.3423 5.3423 0 01-.3465-1.9653c0-.7608.104-1.493.3356-2.1155a4.683 4.683 0 01.9719-1.5958 4.3383 4.3383 0 011.479-1.0257c.5739-.242 1.2043-.3567 1.8864-.3567.6829 0 1.3125.1197 1.8906.3567a4.1245 4.1245 0 011.4816 1.0257 4.7587 4.7587 0 01.9592 1.5958c.2426.6225.3643 1.3547.3643 2.1155zm-17.0198 0c0 .9448.208 1.9932.6238 2.431.4166.4386.955.6579 1.6142.6579.3584 0 .6998-.0523 1.0176-.1502.3186-.0978.5721-.2134.775-.3517V7.0784a8.8706 8.8706 0 00-1.4926-.1906c-.8206-.0236-1.4452.312-1.8847.8468-.4335.5365-.6533 1.476-.6533 2.3516v-.0008zm6.2863 4.4485c0 1.5385-.3938 2.662-1.1866 3.3773-.791.7136-2.0005 1.0712-3.6308 1.0712-.5958 0-1.834-.1156-2.8228-.334l.3643-1.7865c.8282.173 1.9202.2193 2.4932.2193.9077 0 1.555-.1847 1.943-.5533.388-.3686.578-.916.578-1.643v-.3687a6.8289 6.8289 0 01-.8848.3349c-.3634.1096-.786.167-1.261.167-.6246 0-1.1917-.0979-1.7055-.2944a3.5554 3.5554 0 01-1.3244-.8645c-.3642-.3796-.6541-.8579-.8561-1.4289-.2028-.571-.3068-1.59-.3068-2.339 0-.7034.1099-1.5856.3245-2.1735.2198-.5871.5316-1.0949.9542-1.515.4167-.42.9255-.743 1.5213-.98a5.5923 5.5923 0 012.052-.3855c.7353 0 1.4114.092 2.0707.2024.6592.1088 1.2204.2236 1.6776.35v8.945-.0008zM11.5026 4.2418v-.6511c-.0005-.4553-.3704-.8241-.8266-.8241H8.749c-.4561 0-.826.3688-.8265.824v.669c0 .0742.0693.1264.1445.1096a6.0346 6.0346 0 011.6768-.2362 6.125 6.125 0 011.6202.2185.1116.1116 0 00.1386-.1097zm-5.2806.852l-.3296-.3282a.8266.8266 0 00-1.168 0l-.393.3922a.8199.8199 0 000 1.164l.3237.323c.0524.0515.1268.0397.1733-.0117.191-.259.3989-.507.6305-.7372.2374-.2362.48-.4437.7462-.6335.0575-.0354.0634-.1155.017-.1687zm3.5159 2.069v2.818c0 .081.0879.1392.1622.0987l2.5102-1.2964c.0574-.0287.0752-.0987.0464-.1552a3.1237 3.1237 0 00-2.603-1.574c-.0575 0-.115.0456-.115.1097l-.0008-.0009zm.0008 6.789c-2.0933.0005-3.7915-1.6912-3.7947-3.7804C5.9468 8.0821 7.6452 6.39 9.7387 6.391c2.0932-.0005 3.7911 1.6914 3.794 3.7804a3.7783 3.7783 0 01-1.1124 2.675 3.7936 3.7936 0 01-2.6824 1.1054h.0008zM9.738 4.8002c-1.9218 0-3.6975 1.0232-4.6584 2.6841a5.359 5.359 0 000 5.3683c.9609 1.661 2.7366 2.6841 4.6584 2.6841a5.3891 5.3891 0 003.8073-1.5725 5.3675 5.3675 0 001.578-3.7987 5.3574 5.3574 0 00-1.5771-3.797A5.379 5.379 0 009.7387 4.801l-.0008-.0008z",fill:"currentColor",fillRule:"evenodd"})))}function xe(e){return ke.createElement("svg",{width:"15",height:"15","aria-label":e.ariaLabel,role:"img"},ke.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"1.2"},e.children))}function Ne(e){var t=e.translations,r=void 0===t?{}:t,n=r.selectText,o=void 0===n?"to select":n,a=r.selectKeyAriaLabel,c=void 0===a?"Enter key":a,i=r.navigateText,l=void 0===i?"to navigate":i,u=r.navigateUpKeyAriaLabel,s=void 0===u?"Arrow up":u,f=r.navigateDownKeyAriaLabel,m=void 0===f?"Arrow down":f,p=r.closeText,d=void 0===p?"to close":p,h=r.closeKeyAriaLabel,v=void 0===h?"Escape key":h,y=r.searchByText,g=void 0===y?"Search by":y;return ke.createElement(ke.Fragment,null,ke.createElement("div",{className:"DocSearch-Logo"},ke.createElement(Ae,{translations:{searchByText:g}})),ke.createElement("ul",{className:"DocSearch-Commands"},ke.createElement("li",null,ke.createElement("kbd",{className:"DocSearch-Commands-Key"},ke.createElement(xe,{ariaLabel:c},ke.createElement("path",{d:"M12 3.53088v3c0 1-1 2-2 2H4M7 11.53088l-3-3 3-3"}))),ke.createElement("span",{className:"DocSearch-Label"},o)),ke.createElement("li",null,ke.createElement("kbd",{className:"DocSearch-Commands-Key"},ke.createElement(xe,{ariaLabel:m},ke.createElement("path",{d:"M7.5 3.5v8M10.5 8.5l-3 3-3-3"}))),ke.createElement("kbd",{className:"DocSearch-Commands-Key"},ke.createElement(xe,{ariaLabel:s},ke.createElement("path",{d:"M7.5 11.5v-8M10.5 6.5l-3-3-3 3"}))),ke.createElement("span",{className:"DocSearch-Label"},l)),ke.createElement("li",null,ke.createElement("kbd",{className:"DocSearch-Commands-Key"},ke.createElement(xe,{ariaLabel:v},ke.createElement("path",{d:"M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"}))),ke.createElement("span",{className:"DocSearch-Label"},d))))}function Re(e){var t=e.hit,r=e.children;return ke.createElement("a",{href:t.url},r)}function qe(){return ke.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},ke.createElement("path",{d:"M19 4.8a16 16 0 00-2-1.2m-3.3-1.2A16 16 0 001.1 4.7M16.7 8a12 12 0 00-2.8-1.4M10 6a12 12 0 00-6.7 2M12.3 14.7a4 4 0 00-4.5 0M14.5 11.4A8 8 0 0010 10M3 16L18 2M10 18h0"}))}function _e(e){var t=e.translations,r=void 0===t?{}:t,n=r.titleText,o=void 0===n?"Unable to fetch results":n,a=r.helpText,c=void 0===a?"You might want to check your network connection.":a;return ke.createElement("div",{className:"DocSearch-ErrorScreen"},ke.createElement("div",{className:"DocSearch-Screen-Icon"},ke.createElement(qe,null)),ke.createElement("p",{className:"DocSearch-Title"},o),ke.createElement("p",{className:"DocSearch-Help"},c))}function Te(){return ke.createElement("svg",{width:"40",height:"40",viewBox:"0 0 20 20",fill:"none",fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round"},ke.createElement("path",{d:"M15.5 4.8c2 3 1.7 7-1 9.7h0l4.3 4.3-4.3-4.3a7.8 7.8 0 01-9.8 1m-2.2-2.2A7.8 7.8 0 0113.2 2.4M2 18L18 2"}))}var Le=["translations"];function Me(e){return function(e){if(Array.isArray(e))return He(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return He(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return He(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function He(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function Fe(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Ue(e){var t=e.translations,r=void 0===t?{}:t,n=Fe(e,Le),o=r.noResultsText,a=void 0===o?"No results for":o,c=r.suggestedQueryText,i=void 0===c?"Try searching for":c,l=r.reportMissingResultsText,u=void 0===l?"Believe this query should return results?":l,s=r.reportMissingResultsLinkText,f=void 0===s?"Let us know.":s,m=n.state.context.searchSuggestions;return ke.createElement("div",{className:"DocSearch-NoResults"},ke.createElement("div",{className:"DocSearch-Screen-Icon"},ke.createElement(Te,null)),ke.createElement("p",{className:"DocSearch-Title"},a,' "',ke.createElement("strong",null,n.state.query),'"'),m&&m.length>0&&ke.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},ke.createElement("p",{className:"DocSearch-Help"},i,":"),ke.createElement("ul",null,m.slice(0,3).reduce((function(e,t){return[].concat(Me(e),[ke.createElement("li",{key:t},ke.createElement("button",{className:"DocSearch-Prefill",key:t,type:"button",onClick:function(){n.setQuery(t.toLowerCase()+" "),n.refresh(),n.inputRef.current.focus()}},t))])}),[]))),n.getMissingResultsUrl&&ke.createElement("p",{className:"DocSearch-Help"},"".concat(u," "),ke.createElement("a",{href:n.getMissingResultsUrl({query:n.state.query}),target:"_blank",rel:"noopener noreferrer"},f)))}var Be=function(){return ke.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("path",{d:"M17 6v12c0 .52-.2 1-1 1H4c-.7 0-1-.33-1-1V2c0-.55.42-1 1-1h8l5 5zM14 8h-3.13c-.51 0-.87-.34-.87-.87V4",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))};function Ve(e){switch(e.type){case"lvl1":return ke.createElement(Be,null);case"content":return ke.createElement(Ke,null);default:return ke.createElement(ze,null)}}function ze(){return ke.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("path",{d:"M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}function Ke(){return ke.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("path",{d:"M17 5H3h14zm0 5H3h14zm0 5H3h14z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function Je(){return ke.createElement("svg",{className:"DocSearch-Hit-Select-Icon",width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},ke.createElement("path",{d:"M18 3v4c0 2-2 4-4 4H2"}),ke.createElement("path",{d:"M8 17l-6-6 6-6"})))}var $e=["hit","attribute","tagName"];function We(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function Qe(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?We(Object(r),!0).forEach((function(t){Ye(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):We(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function Ye(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function Ge(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Xe(e,t){return t.split(".").reduce((function(e,t){return null!=e&&e[t]?e[t]:null}),e)}function Ze(e){var t=e.hit,r=e.attribute,n=e.tagName,o=void 0===n?"span":n,a=Ge(e,$e);return(0,ke.createElement)(o,Qe(Qe({},a),{},{dangerouslySetInnerHTML:{__html:Xe(t,"_snippetResult.".concat(r,".value"))||Xe(t,r)}}))}function et(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==r)return;var n,o,a=[],c=!0,i=!1;try{for(r=r.call(e);!(c=(n=r.next()).done)&&(a.push(n.value),!t||a.length!==t);c=!0);}catch(l){i=!0,o=l}finally{try{c||null==r.return||r.return()}finally{if(i)throw o}}return a}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return tt(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return tt(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function tt(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function rt(){return rt=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},rt.apply(this,arguments)}function nt(e){return e.collection&&0!==e.collection.items.length?ke.createElement("section",{className:"DocSearch-Hits"},ke.createElement("div",{className:"DocSearch-Hit-source"},e.title),ke.createElement("ul",e.getListProps(),e.collection.items.map((function(t,r){return ke.createElement(ot,rt({key:[e.title,t.objectID].join(":"),item:t,index:r},e))})))):null}function ot(e){var t=e.item,r=e.index,n=e.renderIcon,o=e.renderAction,a=e.getItemProps,c=e.onItemClick,i=e.collection,l=e.hitComponent,u=et(ke.useState(!1),2),s=u[0],f=u[1],m=et(ke.useState(!1),2),p=m[0],d=m[1],h=ke.useRef(null),v=l;return ke.createElement("li",rt({className:["DocSearch-Hit",t.__docsearch_parent&&"DocSearch-Hit--Child",s&&"DocSearch-Hit--deleting",p&&"DocSearch-Hit--favoriting"].filter(Boolean).join(" "),onTransitionEnd:function(){h.current&&h.current()}},a({item:t,source:i.source,onClick:function(){c(t)}})),ke.createElement(v,{hit:t},ke.createElement("div",{className:"DocSearch-Hit-Container"},n({item:t,index:r}),t.hierarchy[t.type]&&"lvl1"===t.type&&ke.createElement("div",{className:"DocSearch-Hit-content-wrapper"},ke.createElement(Ze,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.lvl1"}),t.content&&ke.createElement(Ze,{className:"DocSearch-Hit-path",hit:t,attribute:"content"})),t.hierarchy[t.type]&&("lvl2"===t.type||"lvl3"===t.type||"lvl4"===t.type||"lvl5"===t.type||"lvl6"===t.type)&&ke.createElement("div",{className:"DocSearch-Hit-content-wrapper"},ke.createElement(Ze,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.".concat(t.type)}),ke.createElement(Ze,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),"content"===t.type&&ke.createElement("div",{className:"DocSearch-Hit-content-wrapper"},ke.createElement(Ze,{className:"DocSearch-Hit-title",hit:t,attribute:"content"}),ke.createElement(Ze,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),o({item:t,runDeleteTransition:function(e){f(!0),h.current=e},runFavoriteTransition:function(e){d(!0),h.current=e}}))))}var at=/(<mark>|<\/mark>)/g,ct=RegExp(at.source);function it(e){var t,r,n,o,a,c=e;if(!c.__docsearch_parent&&!e._highlightResult)return e.hierarchy.lvl0;var i=((c.__docsearch_parent?null===(t=c.__docsearch_parent)||void 0===t||null===(r=t._highlightResult)||void 0===r||null===(n=r.hierarchy)||void 0===n?void 0:n.lvl0:null===(o=e._highlightResult)||void 0===o||null===(a=o.hierarchy)||void 0===a?void 0:a.lvl0)||{}).value;return i&&ct.test(i)?i.replace(at,""):i}function lt(){return lt=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},lt.apply(this,arguments)}function ut(e){return ke.createElement("div",{className:"DocSearch-Dropdown-Container"},e.state.collections.map((function(t){if(0===t.items.length)return null;var r=it(t.items[0]);return ke.createElement(nt,lt({},e,{key:t.source.sourceId,title:r,collection:t,renderIcon:function(e){var r,n=e.item,o=e.index;return ke.createElement(ke.Fragment,null,n.__docsearch_parent&&ke.createElement("svg",{className:"DocSearch-Hit-Tree",viewBox:"0 0 24 54"},ke.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},n.__docsearch_parent!==(null===(r=t.items[o+1])||void 0===r?void 0:r.__docsearch_parent)?ke.createElement("path",{d:"M8 6v21M20 27H8.3"}):ke.createElement("path",{d:"M8 6v42M20 27H8.3"}))),ke.createElement("div",{className:"DocSearch-Hit-icon"},ke.createElement(Ve,{type:n.type})))},renderAction:function(){return ke.createElement("div",{className:"DocSearch-Hit-action"},ke.createElement(Je,null))}}))})),e.resultsFooterComponent&&ke.createElement("section",{className:"DocSearch-HitsFooter"},ke.createElement(e.resultsFooterComponent,{state:e.state})))}function st(){return ke.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},ke.createElement("path",{d:"M3.18 6.6a8.23 8.23 0 1112.93 9.94h0a8.23 8.23 0 01-11.63 0"}),ke.createElement("path",{d:"M6.44 7.25H2.55V3.36M10.45 6v5.6M10.45 11.6L13 13"})))}function ft(){return ke.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("path",{d:"M10 14.2L5 17l1-5.6-4-4 5.5-.7 2.5-5 2.5 5 5.6.8-4 4 .9 5.5z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinejoin:"round"}))}function mt(){return ke.createElement("svg",{width:"20",height:"20",viewBox:"0 0 20 20"},ke.createElement("path",{d:"M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}var pt=["translations"];function dt(){return dt=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},dt.apply(this,arguments)}function ht(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function vt(e){var t=e.translations,r=void 0===t?{}:t,n=ht(e,pt),o=r.recentSearchesTitle,a=void 0===o?"Recent":o,c=r.noRecentSearchesText,i=void 0===c?"No recent searches":c,l=r.saveRecentSearchButtonTitle,u=void 0===l?"Save this search":l,s=r.removeRecentSearchButtonTitle,f=void 0===s?"Remove this search from history":s,m=r.favoriteSearchesTitle,p=void 0===m?"Favorite":m,d=r.removeFavoriteSearchButtonTitle,h=void 0===d?"Remove this search from favorites":d;return"idle"===n.state.status&&!1===n.hasCollections?n.disableUserPersonalization?null:ke.createElement("div",{className:"DocSearch-StartScreen"},ke.createElement("p",{className:"DocSearch-Help"},i)):!1===n.hasCollections?null:ke.createElement("div",{className:"DocSearch-Dropdown-Container"},ke.createElement(nt,dt({},n,{title:a,collection:n.state.collections[0],renderIcon:function(){return ke.createElement("div",{className:"DocSearch-Hit-icon"},ke.createElement(st,null))},renderAction:function(e){var t=e.item,r=e.runFavoriteTransition,o=e.runDeleteTransition;return ke.createElement(ke.Fragment,null,ke.createElement("div",{className:"DocSearch-Hit-action"},ke.createElement("button",{className:"DocSearch-Hit-action-button",title:u,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),r((function(){n.favoriteSearches.add(t),n.recentSearches.remove(t),n.refresh()}))}},ke.createElement(ft,null))),ke.createElement("div",{className:"DocSearch-Hit-action"},ke.createElement("button",{className:"DocSearch-Hit-action-button",title:f,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),o((function(){n.recentSearches.remove(t),n.refresh()}))}},ke.createElement(mt,null))))}})),ke.createElement(nt,dt({},n,{title:p,collection:n.state.collections[1],renderIcon:function(){return ke.createElement("div",{className:"DocSearch-Hit-icon"},ke.createElement(ft,null))},renderAction:function(e){var t=e.item,r=e.runDeleteTransition;return ke.createElement("div",{className:"DocSearch-Hit-action"},ke.createElement("button",{className:"DocSearch-Hit-action-button",title:h,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),r((function(){n.favoriteSearches.remove(t),n.refresh()}))}},ke.createElement(mt,null)))}})))}var yt=["translations"];function gt(){return gt=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},gt.apply(this,arguments)}function bt(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var Ot=ke.memo((function(e){var t=e.translations,r=void 0===t?{}:t,n=bt(e,yt);if("error"===n.state.status)return ke.createElement(_e,{translations:null==r?void 0:r.errorScreen});var o=n.state.collections.some((function(e){return e.items.length>0}));return n.state.query?!1===o?ke.createElement(Ue,gt({},n,{translations:null==r?void 0:r.noResultsScreen})):ke.createElement(ut,n):ke.createElement(vt,gt({},n,{hasCollections:o,translations:null==r?void 0:r.startScreen}))}),(function(e,t){return"loading"===t.state.status||"stalled"===t.state.status}));function St(){return ke.createElement("svg",{viewBox:"0 0 38 38",stroke:"currentColor",strokeOpacity:".5"},ke.createElement("g",{fill:"none",fillRule:"evenodd"},ke.createElement("g",{transform:"translate(1 1)",strokeWidth:"2"},ke.createElement("circle",{strokeOpacity:".3",cx:"18",cy:"18",r:"18"}),ke.createElement("path",{d:"M36 18c0-9.94-8.06-18-18-18"},ke.createElement("animateTransform",{attributeName:"transform",type:"rotate",from:"0 18 18",to:"360 18 18",dur:"1s",repeatCount:"indefinite"})))))}var jt=r(830),Et=["translations"];function wt(){return wt=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},wt.apply(this,arguments)}function Pt(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function It(e){var t=e.translations,r=void 0===t?{}:t,n=Pt(e,Et),o=r.resetButtonTitle,a=void 0===o?"Clear the query":o,c=r.resetButtonAriaLabel,i=void 0===c?"Clear the query":c,l=r.cancelButtonText,u=void 0===l?"Cancel":l,s=r.cancelButtonAriaLabel,f=void 0===s?"Cancel":s,m=n.getFormProps({inputElement:n.inputRef.current}).onReset;return ke.useEffect((function(){n.autoFocus&&n.inputRef.current&&n.inputRef.current.focus()}),[n.autoFocus,n.inputRef]),ke.useEffect((function(){n.isFromSelection&&n.inputRef.current&&n.inputRef.current.select()}),[n.isFromSelection,n.inputRef]),ke.createElement(ke.Fragment,null,ke.createElement("form",{className:"DocSearch-Form",onSubmit:function(e){e.preventDefault()},onReset:m},ke.createElement("label",wt({className:"DocSearch-MagnifierLabel"},n.getLabelProps()),ke.createElement(jt.W,null)),ke.createElement("div",{className:"DocSearch-LoadingIndicator"},ke.createElement(St,null)),ke.createElement("input",wt({className:"DocSearch-Input",ref:n.inputRef},n.getInputProps({inputElement:n.inputRef.current,autoFocus:n.autoFocus,maxLength:64}))),ke.createElement("button",{type:"reset",title:a,className:"DocSearch-Reset","aria-label":i,hidden:!n.state.query},ke.createElement(mt,null))),ke.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":f,onClick:n.onClose},u))}var Dt=["_highlightResult","_snippetResult"];function Ct(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function kt(e){return!1===function(){var e="__TEST_KEY__";try{return localStorage.setItem(e,""),localStorage.removeItem(e),!0}catch(t){return!1}}()?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(t){return window.localStorage.setItem(e,JSON.stringify(t))},getItem:function(){var t=window.localStorage.getItem(e);return t?JSON.parse(t):[]}}}function At(e){var t=e.key,r=e.limit,n=void 0===r?5:r,o=kt(t),a=o.getItem().slice(0,n);return{add:function(e){var t=e,r=(t._highlightResult,t._snippetResult,Ct(t,Dt)),c=a.findIndex((function(e){return e.objectID===r.objectID}));c>-1&&a.splice(c,1),a.unshift(r),a=a.slice(0,n),o.setItem(a)},remove:function(e){a=a.filter((function(t){return t.objectID!==e.objectID})),o.setItem(a)},getAll:function(){return a}}}function xt(e){const t=`algoliasearch-client-js-${e.key}`;let r;const n=()=>(void 0===r&&(r=e.localStorage||window.localStorage),r),o=()=>JSON.parse(n().getItem(t)||"{}");return{get:(e,t,r={miss:()=>Promise.resolve()})=>Promise.resolve().then((()=>{const r=JSON.stringify(e),n=o()[r];return Promise.all([n||t(),void 0!==n])})).then((([e,t])=>Promise.all([e,t||r.miss(e)]))).then((([e])=>e)),set:(e,r)=>Promise.resolve().then((()=>{const a=o();return a[JSON.stringify(e)]=r,n().setItem(t,JSON.stringify(a)),r})),delete:e=>Promise.resolve().then((()=>{const r=o();delete r[JSON.stringify(e)],n().setItem(t,JSON.stringify(r))})),clear:()=>Promise.resolve().then((()=>{n().removeItem(t)}))}}function Nt(e){const t=[...e.caches],r=t.shift();return void 0===r?{get:(e,t,r={miss:()=>Promise.resolve()})=>t().then((e=>Promise.all([e,r.miss(e)]))).then((([e])=>e)),set:(e,t)=>Promise.resolve(t),delete:e=>Promise.resolve(),clear:()=>Promise.resolve()}:{get:(e,n,o={miss:()=>Promise.resolve()})=>r.get(e,n,o).catch((()=>Nt({caches:t}).get(e,n,o))),set:(e,n)=>r.set(e,n).catch((()=>Nt({caches:t}).set(e,n))),delete:e=>r.delete(e).catch((()=>Nt({caches:t}).delete(e))),clear:()=>r.clear().catch((()=>Nt({caches:t}).clear()))}}function Rt(e={serializable:!0}){let t={};return{get(r,n,o={miss:()=>Promise.resolve()}){const a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);const c=n(),i=o&&o.miss||(()=>Promise.resolve());return c.then((e=>i(e))).then((()=>c))},set:(r,n)=>(t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)),delete:e=>(delete t[JSON.stringify(e)],Promise.resolve()),clear:()=>(t={},Promise.resolve())}}function qt(e){let t=e.length-1;for(;t>0;t--){const r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function _t(e,t){return t?(Object.keys(t).forEach((r=>{e[r]=t[r](e)})),e):e}function Tt(e,...t){let r=0;return e.replace(/%s/g,(()=>encodeURIComponent(t[r++])))}const Lt="4.13.1",Mt={WithinQueryParameters:0,WithinHeaders:1};function Ht(e,t){const r=e||{},n=r.data||{};return Object.keys(r).forEach((e=>{-1===["timeout","headers","queryParameters","data","cacheable"].indexOf(e)&&(n[e]=r[e])})),{data:Object.entries(n).length>0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}const Ft={Read:1,Write:2,Any:3},Ut=1,Bt=2,Vt=3,zt=12e4;function Kt(e,t=Ut){return{...e,status:t,lastUpdate:Date.now()}}function Jt(e){return"string"==typeof e?{protocol:"https",url:e,accept:Ft.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||Ft.Any}}const $t="GET",Wt="POST";function Qt(e,t){return Promise.all(t.map((t=>e.get(t,(()=>Promise.resolve(Kt(t))))))).then((e=>{const r=e.filter((e=>function(e){return e.status===Ut||Date.now()-e.lastUpdate>zt}(e))),n=e.filter((e=>function(e){return e.status===Vt&&Date.now()-e.lastUpdate<=zt}(e))),o=[...r,...n];return{getTimeout:(e,t)=>(0===n.length&&0===e?1:n.length+3+e)*t,statelessHosts:o.length>0?o.map((e=>Jt(e))):t}}))}function Yt(e,t,r,n){const o=[],a=function(e,t){if(e.method===$t||void 0===e.data&&void 0===t.data)return;const r=Array.isArray(e.data)?e.data:{...e.data,...t.data};return JSON.stringify(r)}(r,n),c=function(e,t){const r={...e.headers,...t.headers},n={};return Object.keys(r).forEach((e=>{const t=r[e];n[e.toLowerCase()]=t})),n}(e,n),i=r.method,l=r.method!==$t?{}:{...r.data,...n.data},u={"x-algolia-agent":e.userAgent.value,...e.queryParameters,...l,...n.queryParameters};let s=0;const f=(t,l)=>{const m=t.pop();if(void 0===m)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:er(o)};const p={data:a,headers:c,method:i,url:Xt(m,r.path,u),connectTimeout:l(s,e.timeouts.connect),responseTimeout:l(s,n.timeout)},d=e=>{const r={request:p,response:e,host:m,triesLeft:t.length};return o.push(r),r},h={onSuccess:e=>function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e),onRetry(r){const n=d(r);return r.isTimedOut&&s++,Promise.all([e.logger.info("Retryable failure",tr(n)),e.hostsCache.set(m,Kt(m,r.isTimedOut?Vt:Bt))]).then((()=>f(t,l)))},onFail(e){throw d(e),function({content:e,status:t},r){let n=e;try{n=JSON.parse(e).message}catch(o){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(n,t,r)}(e,er(o))}};return e.requester.send(p).then((e=>((e,t)=>(e=>{const t=e.status;return e.isTimedOut||(({isTimedOut:e,status:t})=>!e&&0==~~t)(e)||2!=~~(t/100)&&4!=~~(t/100)})(e)?t.onRetry(e):(({status:e})=>2==~~(e/100))(e)?t.onSuccess(e):t.onFail(e))(e,h)))};return Qt(e.hostsCache,t).then((e=>f([...e.statelessHosts].reverse(),e.getTimeout)))}function Gt(e){const t={value:`Algolia for JavaScript (${e})`,add(e){const r=`; ${e.segment}${void 0!==e.version?` (${e.version})`:""}`;return-1===t.value.indexOf(r)&&(t.value=`${t.value}${r}`),t}};return t}function Xt(e,t,r){const n=Zt(r);let o=`${e.protocol}://${e.url}/${"/"===t.charAt(0)?t.substr(1):t}`;return n.length&&(o+=`?${n}`),o}function Zt(e){return Object.keys(e).map((t=>{return Tt("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function er(e){return e.map((e=>tr(e)))}function tr(e){const t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...e,request:{...e.request,headers:{...e.request.headers,...t}}}}const rr=e=>{const t=e.appId,r=function(e,t,r){const n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:()=>e===Mt.WithinHeaders?n:{},queryParameters:()=>e===Mt.WithinQueryParameters?n:{}}}(void 0!==e.authMode?e.authMode:Mt.WithinHeaders,t,e.apiKey),n=function(e){const{hostsCache:t,logger:r,requester:n,requestsCache:o,responsesCache:a,timeouts:c,userAgent:i,hosts:l,queryParameters:u,headers:s}=e,f={hostsCache:t,logger:r,requester:n,requestsCache:o,responsesCache:a,timeouts:c,userAgent:i,headers:s,queryParameters:u,hosts:l.map((e=>Jt(e))),read(e,t){const r=Ht(t,f.timeouts.read),n=()=>Yt(f,f.hosts.filter((e=>0!=(e.accept&Ft.Read))),e,r);if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();const o={request:e,mappedRequestOptions:r,transporter:{queryParameters:f.queryParameters,headers:f.headers}};return f.responsesCache.get(o,(()=>f.requestsCache.get(o,(()=>f.requestsCache.set(o,n()).then((e=>Promise.all([f.requestsCache.delete(o),e])),(e=>Promise.all([f.requestsCache.delete(o),Promise.reject(e)]))).then((([e,t])=>t))))),{miss:e=>f.responsesCache.set(o,e)})},write:(e,t)=>Yt(f,f.hosts.filter((e=>0!=(e.accept&Ft.Write))),e,Ht(t,f.timeouts.write))};return f}({hosts:[{url:`${t}-dsn.algolia.net`,accept:Ft.Read},{url:`${t}.algolia.net`,accept:Ft.Write}].concat(qt([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}])),...e,headers:{...r.headers(),"content-type":"application/x-www-form-urlencoded",...e.headers},queryParameters:{...r.queryParameters(),...e.queryParameters}}),o={transporter:n,appId:t,addAlgoliaAgent(e,t){n.userAgent.add({segment:e,version:t})},clearCache:()=>Promise.all([n.requestsCache.clear(),n.responsesCache.clear()]).then((()=>{}))};return _t(o,e.methods)},nr=e=>(t,r)=>t.method===$t?e.transporter.read(t,r):e.transporter.write(t,r),or=e=>(t,r={})=>_t({transporter:e.transporter,appId:e.appId,indexName:t},r.methods),ar=e=>(t,r)=>{const n=t.map((e=>({...e,params:Zt(e.params||{})})));return e.transporter.read({method:Wt,path:"1/indexes/*/queries",data:{requests:n},cacheable:!0},r)},cr=e=>(t,r)=>Promise.all(t.map((t=>{const{facetName:n,facetQuery:o,...a}=t.params;return or(e)(t.indexName,{methods:{searchForFacetValues:ur}}).searchForFacetValues(n,o,{...r,...a})}))),ir=e=>(t,r,n)=>e.transporter.read({method:Wt,path:Tt("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:r},cacheable:!0},n),lr=e=>(t,r)=>e.transporter.read({method:Wt,path:Tt("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r),ur=e=>(t,r,n)=>e.transporter.read({method:Wt,path:Tt("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n),sr=1,fr=2,mr=3;function pr(e,t,r){const n={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:e=>new Promise((t=>{const r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((t=>r.setRequestHeader(t,e.headers[t])));const n=(e,n)=>setTimeout((()=>{r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e),o=n(e.connectTimeout,"Connection timeout");let a;r.onreadystatechange=()=>{r.readyState>r.OPENED&&void 0===a&&(clearTimeout(o),a=n(e.responseTimeout,"Socket timeout"))},r.onerror=()=>{0===r.status&&(clearTimeout(o),clearTimeout(a),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=()=>{clearTimeout(o),clearTimeout(a),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))},logger:(o=mr,{debug:(e,t)=>(sr>=o&&console.debug(e,t),Promise.resolve()),info:(e,t)=>(fr>=o&&console.info(e,t),Promise.resolve()),error:(e,t)=>(console.error(e,t),Promise.resolve())}),responsesCache:Rt(),requestsCache:Rt({serializable:!1}),hostsCache:Nt({caches:[xt({key:`4.13.1-${e}`}),Rt()]}),userAgent:Gt(Lt).add({segment:"Browser",version:"lite"}),authMode:Mt.WithinQueryParameters};var o;return rr({...n,...r,methods:{search:ar,searchForFacetValues:cr,multipleQueries:ar,multipleSearchForFacetValues:cr,customRequest:nr,initIndex:e=>t=>or(e)(t,{methods:{search:lr,searchForFacetValues:ur,findAnswers:ir}})}})}pr.version=Lt;const dr=pr;var hr="3.2.0";function vr(){}function yr(e){return e}function gr(e,t){return e.reduce((function(e,r){var n=t(r);return e.hasOwnProperty(n)||(e[n]=[]),e[n].length<5&&e[n].push(r),e}),{})}var br=["footer","searchBox"];function Or(){return Or=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},Or.apply(this,arguments)}function Sr(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function jr(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?Sr(Object(r),!0).forEach((function(t){Er(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):Sr(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function Er(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function wr(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==r)return;var n,o,a=[],c=!0,i=!1;try{for(r=r.call(e);!(c=(n=r.next()).done)&&(a.push(n.value),!t||a.length!==t);c=!0);}catch(l){i=!0,o=l}finally{try{c||null==r.return||r.return()}finally{if(i)throw o}}return a}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return Pr(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return Pr(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Pr(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function Ir(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Dr(e){var t=e.appId,r=e.apiKey,n=e.indexName,o=e.placeholder,a=void 0===o?"Search docs":o,c=e.searchParameters,i=e.onClose,l=void 0===i?vr:i,u=e.transformItems,s=void 0===u?yr:u,f=e.hitComponent,m=void 0===f?Re:f,p=e.resultsFooterComponent,d=void 0===p?function(){return null}:p,h=e.navigator,v=e.initialScrollY,y=void 0===v?0:v,g=e.transformSearchClient,b=void 0===g?yr:g,O=e.disableUserPersonalization,S=void 0!==O&&O,j=e.initialQuery,E=void 0===j?"":j,w=e.translations,P=void 0===w?{}:w,I=e.getMissingResultsUrl,D=P.footer,C=P.searchBox,k=Ir(P,br),A=wr(ke.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),x=A[0],N=A[1],R=ke.useRef(null),q=ke.useRef(null),_=ke.useRef(null),T=ke.useRef(null),L=ke.useRef(null),M=ke.useRef(10),H=ke.useRef("undefined"!=typeof window?window.getSelection().toString().slice(0,64):"").current,F=ke.useRef(E||H).current,U=function(e,t,r){return ke.useMemo((function(){var n=dr(e,t);return n.addAlgoliaAgent("docsearch",hr),!1===/docsearch.js \(.*\)/.test(n.transporter.userAgent.value)&&n.addAlgoliaAgent("docsearch-react",hr),r(n)}),[e,t,r])}(t,r,b),B=ke.useRef(At({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(n),limit:10})).current,V=ke.useRef(At({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(n),limit:0===B.getAll().length?7:4})).current,z=ke.useCallback((function(e){if(!S){var t="content"===e.type?e.__docsearch_parent:e;t&&-1===B.getAll().findIndex((function(e){return e.objectID===t.objectID}))&&V.add(t)}}),[B,V,S]),K=ke.useMemo((function(){return Ce({id:"docsearch",defaultActiveItemId:0,placeholder:a,openOnFocus:!0,initialState:{query:F,context:{searchSuggestions:[]}},navigator:h,onStateChange:function(e){N(e.state)},getSources:function(e){var t=e.query,r=e.state,o=e.setContext,a=e.setStatus;return t?U.search([{query:t,indexName:n,params:jr({attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(M.current),"hierarchy.lvl2:".concat(M.current),"hierarchy.lvl3:".concat(M.current),"hierarchy.lvl4:".concat(M.current),"hierarchy.lvl5:".concat(M.current),"hierarchy.lvl6:".concat(M.current),"content:".concat(M.current)],snippetEllipsisText:"\u2026",highlightPreTag:"<mark>",highlightPostTag:"</mark>",hitsPerPage:20},c)}]).catch((function(e){throw"RetryError"===e.name&&a("error"),e})).then((function(e){var t=e.results[0],n=t.hits,a=t.nbHits,c=gr(n,(function(e){return it(e)}));return r.context.searchSuggestions.length<Object.keys(c).length&&o({searchSuggestions:Object.keys(c)}),o({nbHits:a}),Object.values(c).map((function(e,t){return{sourceId:"hits".concat(t),onSelect:function(e){var t=e.item,r=e.event;z(t),r.shiftKey||r.ctrlKey||r.metaKey||l()},getItemUrl:function(e){return e.item.url},getItems:function(){return Object.values(gr(e,(function(e){return e.hierarchy.lvl1}))).map(s).map((function(e){return e.map((function(t){return jr(jr({},t),{},{__docsearch_parent:"lvl1"!==t.type&&e.find((function(e){return"lvl1"===e.type&&e.hierarchy.lvl1===t.hierarchy.lvl1}))})}))})).flat()}}}))})):S?[]:[{sourceId:"recentSearches",onSelect:function(e){var t=e.item,r=e.event;z(t),r.shiftKey||r.ctrlKey||r.metaKey||l()},getItemUrl:function(e){return e.item.url},getItems:function(){return V.getAll()}},{sourceId:"favoriteSearches",onSelect:function(e){var t=e.item,r=e.event;z(t),r.shiftKey||r.ctrlKey||r.metaKey||l()},getItemUrl:function(e){return e.item.url},getItems:function(){return B.getAll()}}]}})}),[n,c,U,l,V,B,z,F,a,h,s,S]),J=K.getEnvironmentProps,$=K.getRootProps,W=K.refresh;return function(e){var t=e.getEnvironmentProps,r=e.panelElement,n=e.formElement,o=e.inputElement;ke.useEffect((function(){if(r&&n&&o){var e=t({panelElement:r,formElement:n,inputElement:o}),a=e.onTouchStart,c=e.onTouchMove;return window.addEventListener("touchstart",a),window.addEventListener("touchmove",c),function(){window.removeEventListener("touchstart",a),window.removeEventListener("touchmove",c)}}}),[t,r,n,o])}({getEnvironmentProps:J,panelElement:T.current,formElement:_.current,inputElement:L.current}),function(e){var t=e.container;ke.useEffect((function(){if(t){var e=t.querySelectorAll("a[href]:not([disabled]), button:not([disabled]), input:not([disabled])"),r=e[0],n=e[e.length-1];return t.addEventListener("keydown",o),function(){t.removeEventListener("keydown",o)}}function o(e){"Tab"===e.key&&(e.shiftKey?document.activeElement===r&&(e.preventDefault(),n.focus()):document.activeElement===n&&(e.preventDefault(),r.focus()))}}),[t])}({container:R.current}),ke.useEffect((function(){return document.body.classList.add("DocSearch--active"),function(){var e,t;document.body.classList.remove("DocSearch--active"),null===(e=(t=window).scrollTo)||void 0===e||e.call(t,0,y)}}),[]),ke.useEffect((function(){window.matchMedia("(max-width: 768px)").matches&&(M.current=5)}),[]),ke.useEffect((function(){T.current&&(T.current.scrollTop=0)}),[x.query]),ke.useEffect((function(){F.length>0&&(W(),L.current&&L.current.focus())}),[F,W]),ke.useEffect((function(){function e(){if(q.current){var e=.01*window.innerHeight;q.current.style.setProperty("--docsearch-vh","".concat(e,"px"))}}return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[]),ke.createElement("div",Or({ref:R},$({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container","stalled"===x.status&&"DocSearch-Container--Stalled","error"===x.status&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(e){e.target===e.currentTarget&&l()}}),ke.createElement("div",{className:"DocSearch-Modal",ref:q},ke.createElement("header",{className:"DocSearch-SearchBar",ref:_},ke.createElement(It,Or({},K,{state:x,autoFocus:0===F.length,inputRef:L,isFromSelection:Boolean(F)&&F===H,translations:C,onClose:l}))),ke.createElement("div",{className:"DocSearch-Dropdown",ref:T},ke.createElement(Ot,Or({},K,{indexName:n,state:x,hitComponent:m,resultsFooterComponent:d,disableUserPersonalization:S,recentSearches:V,favoriteSearches:B,inputRef:L,translations:k,getMissingResultsUrl:I,onItemClick:function(e){z(e),l()}}))),ke.createElement("footer",{className:"DocSearch-Footer"},ke.createElement(Ne,{translations:D}))))}}}]); \ No newline at end of file diff --git a/docs/assets/js/695a8bbb.23b6fade.js b/docs/assets/js/695a8bbb.23b6fade.js deleted file mode 100644 index c47a476ec5..0000000000 --- a/docs/assets/js/695a8bbb.23b6fade.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7220],{9491:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.0.x","label":"v1.0.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v1.0.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v1.0.x/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/v1.0.x/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/v1.0.x/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/v1.0.x/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v1.0.x/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/v1.0.x/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/v1.0.x/customization","docId":"customization"},{"type":"link","label":"Metrics","href":"/eraser/docs/v1.0.x/metrics","docId":"metrics"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v1.0.x/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/v1.0.x/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v1.0.x/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/v1.0.x/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v1.0.x/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/v1.0.x/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v1.0.x/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/695a8bbb.ab71b31c.js b/docs/assets/js/695a8bbb.ab71b31c.js new file mode 100644 index 0000000000..2c9aa4560f --- /dev/null +++ b/docs/assets/js/695a8bbb.ab71b31c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7220],{9491:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v1.0.x","label":"v1.0.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v1.0.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v1.0.x/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/v1.0.x/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/v1.0.x/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/v1.0.x/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v1.0.x/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/v1.0.x/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/v1.0.x/customization","docId":"customization","unlisted":false},{"type":"link","label":"Metrics","href":"/eraser/docs/v1.0.x/metrics","docId":"metrics","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v1.0.x/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/v1.0.x/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v1.0.x/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/v1.0.x/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v1.0.x/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/v1.0.x/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v1.0.x/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/6af0c1ea.4be63f6e.js b/docs/assets/js/6af0c1ea.4be63f6e.js deleted file mode 100644 index f672483fa1..0000000000 --- a/docs/assets/js/6af0c1ea.4be63f6e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5954],{3905:(e,r,t)=>{t.d(r,{Zo:()=>l,kt:()=>f});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?i(Object(t),!0).forEach((function(r){o(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function c(e,r){if(null==e)return{};var t,n,o=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},l=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},v=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),v=p(t),f=o,y=v["".concat(s,".").concat(f)]||v[f]||u[f]||i;return t?n.createElement(y,a(a({ref:r},l),{},{components:t})):n.createElement(y,a({ref:r},l))}));function f(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=v;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p<i;p++)a[p]=t[p];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}v.displayName="MDXCreateElement"},1336:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i={title:"Trivy"},a=void 0,c={unversionedId:"trivy",id:"version-v1.0.x/trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.0.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v1.0.x/trivy",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v1.0.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v1.0.x/faq"}},s={},p=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],l={toc:p};function u(e){let{components:r,...t}=e;return(0,o.kt)("wrapper",(0,n.Z)({},l,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,o.kt)("p",null,"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"Customization")," for more details on configuring the scanner."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/6af0c1ea.e59808b7.js b/docs/assets/js/6af0c1ea.e59808b7.js new file mode 100644 index 0000000000..68d32e8db3 --- /dev/null +++ b/docs/assets/js/6af0c1ea.e59808b7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5954],{5967:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var n=r(5893),i=r(1151);const o={title:"Trivy"},s=void 0,a={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.0.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v1.0.x/trivy",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v1.0.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v1.0.x/faq"}},c={},d=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function v(e){const t={a:"a",h2:"h2",p:"p",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,n.jsxs)(t.p,{children:["The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,n.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"Customization"})," for more details on configuring the scanner."]})]})}function u(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(v,{...e})}):v(e)}},1151:(e,t,r)=>{r.d(t,{Z:()=>a,a:()=>s});var n=r(7294);const i={},o=n.createContext(i);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/6b8e46b3.1f13278c.js b/docs/assets/js/6b8e46b3.1f13278c.js new file mode 100644 index 0000000000..ace20022c9 --- /dev/null +++ b/docs/assets/js/6b8e46b3.1f13278c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7499],{5613:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>f,frontMatter:()=>d,metadata:()=>i,toc:()=>u});var n=t(5893),c=t(1151);const d={title:"Code of Conduct"},s=void 0,i={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.3.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/contributing"}},r={},u=[];function a(e){const o={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["This project has adopted the ",(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"Resources:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:o}={...(0,c.a)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,o,t)=>{t.d(o,{Z:()=>i,a:()=>s});var n=t(7294);const c={},d=n.createContext(c);function s(e){const o=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(d.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/6b8e46b3.2a4f2d74.js b/docs/assets/js/6b8e46b3.2a4f2d74.js deleted file mode 100644 index ff2b242751..0000000000 --- a/docs/assets/js/6b8e46b3.2a4f2d74.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7499],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l<c;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},6370:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"version-v1.3.x/code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.3.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/code-of-conduct",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/6ec64a11.ac3c351f.js b/docs/assets/js/6ec64a11.ac3c351f.js deleted file mode 100644 index cf48e505c4..0000000000 --- a/docs/assets/js/6ec64a11.ac3c351f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5255],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m<l;m++)i[m]=n[m];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}k.displayName="MDXCreateElement"},5952:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"version-v1.0.x/setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.0.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v1.0.x/setup",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/v1.0.x/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/v1.0.x/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-eraser ERASER_IMG=eraser:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n eraser:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-eraser"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-eraser"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/6ec64a11.e804f073.js b/docs/assets/js/6ec64a11.e804f073.js new file mode 100644 index 0000000000..b264433f5d --- /dev/null +++ b/docs/assets/js/6ec64a11.e804f073.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5255],{3682:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.0.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v1.0.x/setup",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/v1.0.x/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/v1.0.x/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-eraser ERASER_IMG=eraser:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n eraser:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-eraser"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-eraser"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/70b084fe.021d30e0.js b/docs/assets/js/70b084fe.021d30e0.js deleted file mode 100644 index 9156103111..0000000000 --- a/docs/assets/js/70b084fe.021d30e0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9291],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,v=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var s=2;s<i;s++)o[s]=r[s];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},9828:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"version-v1.1.x/architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.1.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v1.1.x/architecture",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v1.1.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v1.1.x/manual-removal"}},c={},s=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],u={toc:s};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/70b084fe.e3b3cc0e.js b/docs/assets/js/70b084fe.e3b3cc0e.js new file mode 100644 index 0000000000..13a39f8828 --- /dev/null +++ b/docs/assets/js/70b084fe.e3b3cc0e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9291],{2298:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,o={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.1.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v1.1.x/architecture",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v1.1.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v1.1.x/manual-removal"}},l={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>o,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/7196cdd1.5bf303c3.js b/docs/assets/js/7196cdd1.5bf303c3.js deleted file mode 100644 index b9077d1d22..0000000000 --- a/docs/assets/js/7196cdd1.5bf303c3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4404],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,c(c({ref:t},p),{},{components:n})):r.createElement(f,c({ref:t},p))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var l=2;l<o;l++)c[l]=n[l];return r.createElement.apply(null,c)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},9743:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const o={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"version-v1.2.x/custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.2.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v1.2.x/custom-scanner",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v1.2.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v1.2.x/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],p={toc:l};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,a.kt)("p",null,"To create a custom scanner for non-compliant images, use the following ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser-scanner-template/"},"template"),"."),(0,a.kt)("p",null,"In order to customize your scanner, start by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},"NewImageProvider()"),". The ImageProvider interface can be found can be found ",(0,a.kt)("a",{parentName:"p",href:"../../pkg/scanners/template/scanner_template.go"},"here"),". "),(0,a.kt)("p",null,"The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,a.kt)("inlineCode",{parentName:"p"},"ReceiveImages()")," function. Process these images with your customized scanner and threshold, and use ",(0,a.kt)("inlineCode",{parentName:"p"},"SendImages()")," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,a.kt)("inlineCode",{parentName:"p"},"Finish()"),"."),(0,a.kt)("p",null,"When complete, provide your custom scanner image to Eraser in deployment."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/7196cdd1.e3825316.js b/docs/assets/js/7196cdd1.e3825316.js new file mode 100644 index 0000000000..411e554f50 --- /dev/null +++ b/docs/assets/js/7196cdd1.e3825316.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4404],{6311:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var r=t(5893),s=t(1151);const o={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.2.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v1.2.x/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v1.2.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v1.2.x/trivy"}},i={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsxs)(n.p,{children:["To create a custom scanner for non-compliant images, use the following ",(0,r.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser-scanner-template/",children:"template"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In order to customize your scanner, start by creating a ",(0,r.jsx)(n.code,{children:"NewImageProvider()"}),". The ImageProvider interface can be found can be found ",(0,r.jsx)(n.a,{href:"../../pkg/scanners/template/scanner_template.go",children:"here"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,r.jsx)(n.code,{children:"ReceiveImages()"})," function. Process these images with your customized scanner and threshold, and use ",(0,r.jsx)(n.code,{children:"SendImages()"})," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,r.jsx)(n.code,{children:"Finish()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"When complete, provide your custom scanner image to Eraser in deployment."})]})}function u(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const s={},o=r.createContext(s);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/72e14192.52383938.js b/docs/assets/js/72e14192.52383938.js new file mode 100644 index 0000000000..dc24cc7a9e --- /dev/null +++ b/docs/assets/js/72e14192.52383938.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7239],{4363:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var t=a(5893),s=a(1151);const r={title:"Quick Start"},i=void 0,l={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/docs/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/next/quick-start",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/next/installation"},next:{title:"Architecture",permalink:"/eraser/docs/next/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,t.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,t.jsxs)(n.p,{children:["After following the ",(0,t.jsx)(n.a,{href:"/eraser/docs/next/installation",children:"install instructions"}),", we'll apply a demo ",(0,t.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,t.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,t.jsxs)(n.p,{children:["First, apply the ",(0,t.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, verify that the Pods are running or completed. After the ",(0,t.jsx)(n.code,{children:"alpine"})," Pods complete, you may see a ",(0,t.jsx)(n.code,{children:"CrashLoopBackoff"})," status. This is expected behavior from the ",(0,t.jsx)(n.code,{children:"alpine"})," image and can be ignored for the tutorial."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n"})}),"\n",(0,t.jsx)(n.p,{children:"Delete the DaemonSet:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl delete daemonset alpine\n"})}),"\n",(0,t.jsx)(n.p,{children:"Verify that the Pods have been deleted:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNo resources found in default namespace.\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To verify that the ",(0,t.jsx)(n.code,{children:"alpine"})," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."]}),"\n",(0,t.jsx)(n.p,{children:"List the nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n"})}),"\n",(0,t.jsxs)(n.p,{children:["List the images then filter for ",(0,t.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,t.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,t.jsx)(n.code,{children:"manager.scheduling.repeatInterval"})," setting in the ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". The default interval is 24 hours (",(0,t.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,t.jsx)(n.p,{children:"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,t.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,t.jsx)(n.code,{children:"components.scanner.enabled"})," value to ",(0,t.jsx)(n.code,{children:"false"})," using the ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". In this case, each collector pod will hold 2 containers: collector and remover."]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>l,a:()=>i});var t=a(7294);const s={},r=t.createContext(s);function i(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/72e14192.5d76082f.js b/docs/assets/js/72e14192.5d76082f.js deleted file mode 100644 index 7b3ff86d4e..0000000000 --- a/docs/assets/js/72e14192.5d76082f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7239],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function o(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,i(i({ref:n},p),{},{components:t})):a.createElement(k,i({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,i=new Array(l);i[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var c=2;c<l;c++)i[c]=t[c];return a.createElement.apply(null,i)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},4181:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},i=void 0,o={unversionedId:"quick-start",id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/docs/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/next/quick-start",draft:!1,tags:[],version:"current",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/next/installation"},next:{title:"Architecture",permalink:"/eraser/docs/next/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/next/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n")),(0,r.kt)("p",null,"Next, verify that the Pods are running or completed. After the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," Pods complete, you may see a ",(0,r.kt)("inlineCode",{parentName:"p"},"CrashLoopBackoff")," status. This is expected behavior from the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," image and can be ignored for the tutorial."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n")),(0,r.kt)("p",null,"Delete the DaemonSet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl delete daemonset alpine\n")),(0,r.kt)("p",null,"Verify that the Pods have been deleted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNo resources found in default namespace.\n")),(0,r.kt)("p",null,"To verify that the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."),(0,r.kt)("p",null,"List the nodes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.scheduling.repeatInterval")," setting in the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.enabled")," value to ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," using the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". In this case, each collector pod will hold 2 containers: collector and remover.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/72ffabc7.89379632.js b/docs/assets/js/72ffabc7.89379632.js new file mode 100644 index 0000000000..5ac2e078bc --- /dev/null +++ b/docs/assets/js/72ffabc7.89379632.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8301],{2274:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var s=n(5893),r=n(1151);const a={title:"Installation"},i=void 0,o={id:"installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.0.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v1.0.x/installation",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v1.0.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v1.0.x/quick-start"}},l={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.0.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>i});var s=n(7294);const r={},a=s.createContext(r);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/72ffabc7.d08704ae.js b/docs/assets/js/72ffabc7.d08704ae.js deleted file mode 100644 index 5a8301be7d..0000000000 --- a/docs/assets/js/72ffabc7.d08704ae.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8301],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,i(i({ref:t},p),{},{components:r})):n.createElement(d,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<o;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},2575:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},i=void 0,l={unversionedId:"installation",id:"version-v1.0.x/installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.0.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v1.0.x/installation",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v1.0.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v1.0.x/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.0.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/7b11c903.40de134e.js b/docs/assets/js/7b11c903.40de134e.js new file mode 100644 index 0000000000..f02509554e --- /dev/null +++ b/docs/assets/js/7b11c903.40de134e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5178],{360:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var i=n(5893),r=n(1151);const t={title:"Exclusion"},o=void 0,a={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/docs/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/next/exclusion",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/next/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/next/customization"}},c={},l=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function d(e){const s={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,i.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,i.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,i.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,i.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,i.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,i.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,i.jsxs)(s.p,{children:["Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.jsx)(s.code,{children:"include"})," or ",(0,i.jsx)(s.code,{children:"exclude"})," from the cleanup process using the configmap. For more information, see the section on ",(0,i.jsx)(s.a,{href:"https://eraser-dev.github.io/eraser/docs/customization",children:"customization"}),"."]})]})}function u(e={}){const{wrapper:s}={...(0,r.a)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,s,n)=>{n.d(s,{Z:()=>a,a:()=>o});var i=n(7294);const r={},t=i.createContext(r);function o(e){const s=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(t.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/7b11c903.ce482ce3.js b/docs/assets/js/7b11c903.ce482ce3.js deleted file mode 100644 index f12d41cba0..0000000000 --- a/docs/assets/js/7b11c903.ce482ce3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5178],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function o(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?a(Object(t),!0).forEach((function(r){i(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function s(e,r){if(null==e)return{};var t,n,i=function(e,r){if(null==e)return{};var t,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)t=a[n],r.indexOf(t)>=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)t=a[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=n.createContext({}),c=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):o(o({},r),e)),t},p=function(e){var r=c(e.components);return n.createElement(l.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(t),m=i,f=d["".concat(l,".").concat(m)]||d[m]||u[m]||a;return t?n.createElement(f,o(o({ref:r},p),{},{components:t})):n.createElement(f,o({ref:r},p))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var a=t.length,o=new Array(a);o[0]=d;var s={};for(var l in r)hasOwnProperty.call(r,l)&&(s[l]=r[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,o[1]=s;for(var c=2;c<a;c++)o[c]=t[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,t)}d.displayName="MDXCreateElement"},8965:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>o,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var n=t(7462),i=(t(7294),t(3905));const a={title:"Exclusion"},o=void 0,s={unversionedId:"exclusion",id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/docs/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/next/exclusion",draft:!1,tags:[],version:"current",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/next/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/next/customization"}},l={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],p={toc:c};function u(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the configmap. For more information, see the section on ",(0,i.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization"},"customization"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/7c6883b5.468dab34.js b/docs/assets/js/7c6883b5.468dab34.js deleted file mode 100644 index f862773faa..0000000000 --- a/docs/assets/js/7c6883b5.468dab34.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[783],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,i(i({ref:t},p),{},{components:r})):n.createElement(d,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<o;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},5222:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},i=void 0,l={unversionedId:"installation",id:"version-v1.1.x/installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.1.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v1.1.x/installation",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v1.1.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v1.1.x/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/7c6883b5.a26ba92b.js b/docs/assets/js/7c6883b5.a26ba92b.js new file mode 100644 index 0000000000..096330effe --- /dev/null +++ b/docs/assets/js/7c6883b5.a26ba92b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[783],{8650:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var s=n(5893),r=n(1151);const a={title:"Installation"},i=void 0,o={id:"installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.1.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v1.1.x/installation",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v1.1.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v1.1.x/quick-start"}},l={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>i});var s=n(7294);const r={},a=s.createContext(r);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/7d415946.1d8d923e.js b/docs/assets/js/7d415946.1d8d923e.js deleted file mode 100644 index eb2c4b8172..0000000000 --- a/docs/assets/js/7d415946.1d8d923e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6705],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>g});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(r),g=a,d=m["".concat(s,".").concat(g)]||m[g]||u[g]||i;return r?n.createElement(d,l(l({ref:t},p),{},{components:r})):n.createElement(d,l({ref:t},p))}));function g(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c<i;c++)l[c]=r[c];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},8134:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/docs/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/next/releasing",draft:!1,tags:[],version:"current",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/next/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/next/custom-scanner"}},s={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2},{value:"Notifying",id:"notifying",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"create-release-pull-request"},"Create Release Pull Request"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Go to ",(0,a.kt)("inlineCode",{parentName:"li"},"create_release_pull_request")," workflow under actions."),(0,a.kt)("li",{parentName:"ol"},"Select run workflow, and use the workflow from your branch. "),(0,a.kt)("li",{parentName:"ol"},"Input release version with the semantic version identifying the release."),(0,a.kt)("li",{parentName:"ol"},"Click run workflow and review the PR created by github-actions.")),(0,a.kt)("h1",{id:"releasing"},"Releasing"),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main"),", tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/remover"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/collector"),", and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-trivy-scanner")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))),(0,a.kt)("h2",{id:"notifying"},"Notifying"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Send an email to the ",(0,a.kt)("a",{parentName:"li",href:"https://groups.google.com/g/eraser-dev"},"Eraser mailing list")," announcing the release, with links to GitHub."),(0,a.kt)("li",{parentName:"ol"},"Post a message on the ",(0,a.kt)("a",{parentName:"li",href:"https://kubernetes.slack.com/archives/C03Q8KV8YQ4"},"Eraser Slack channel")," with the same information.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/7d415946.b8046362.js b/docs/assets/js/7d415946.b8046362.js new file mode 100644 index 0000000000..4e6b64956b --- /dev/null +++ b/docs/assets/js/7d415946.b8046362.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6705],{2152:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>d,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var s=r(5893),i=r(1151);const t={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/docs/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/next/releasing",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/next/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/next/custom-scanner"}},o={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2},{value:"Notifying",id:"notifying",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"create-release-pull-request",children:"Create Release Pull Request"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Go to ",(0,s.jsx)(n.code,{children:"create_release_pull_request"})," workflow under actions."]}),"\n",(0,s.jsx)(n.li,{children:"Select run workflow, and use the workflow from your branch."}),"\n",(0,s.jsx)(n.li,{children:"Input release version with the semantic version identifying the release."}),"\n",(0,s.jsx)(n.li,{children:"Click run workflow and review the PR created by github-actions."}),"\n"]}),"\n",(0,s.jsx)(n.h1,{id:"releasing",children:"Releasing"}),"\n",(0,s.jsxs)(n.ol,{start:"5",children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Once the PR is merged to ",(0,s.jsx)(n.code,{children:"main"}),", tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(n.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/remover"}),", ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser-manager"}),", ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/collector"}),", and ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"notifying",children:"Notifying"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Send an email to the ",(0,s.jsx)(n.a,{href:"https://groups.google.com/g/eraser-dev",children:"Eraser mailing list"})," announcing the release, with links to GitHub."]}),"\n",(0,s.jsxs)(n.li,{children:["Post a message on the ",(0,s.jsx)(n.a,{href:"https://kubernetes.slack.com/archives/C03Q8KV8YQ4",children:"Eraser Slack channel"})," with the same information."]}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>l});var s=r(7294);const i={},t=s.createContext(i);function l(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/7d6336d8.545b329a.js b/docs/assets/js/7d6336d8.545b329a.js new file mode 100644 index 0000000000..ef687b3601 --- /dev/null +++ b/docs/assets/js/7d6336d8.545b329a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3052],{5984:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var s=n(5893),a=n(1151);const r={title:"Installation"},i=void 0,o={id:"installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.3.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/installation",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/"},next:{title:"Quick Start",permalink:"/eraser/docs/quick-start"}},l={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,a.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>i});var s=n(7294);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/7d6336d8.d9e3c66f.js b/docs/assets/js/7d6336d8.d9e3c66f.js deleted file mode 100644 index 6a55642e7a..0000000000 --- a/docs/assets/js/7d6336d8.d9e3c66f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3052],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,i(i({ref:t},p),{},{components:r})):n.createElement(d,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<o;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},1594:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},i=void 0,l={unversionedId:"installation",id:"version-v1.3.x/installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v1.3.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/installation",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/"},next:{title:"Quick Start",permalink:"/eraser/docs/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/85c70040.6420b355.js b/docs/assets/js/85c70040.6420b355.js new file mode 100644 index 0000000000..4d4cedfc6d --- /dev/null +++ b/docs/assets/js/85c70040.6420b355.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3695],{8523:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.3.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/installation"}},c={},d=[];function l(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/85c70040.e0419889.js b/docs/assets/js/85c70040.e0419889.js deleted file mode 100644 index 1f582a07d8..0000000000 --- a/docs/assets/js/85c70040.e0419889.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3695],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(c,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},8741:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",s={unversionedId:"introduction",id:"version-v1.3.x/introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.3.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/installation"}},c={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/8c9fcf50.cf3bd3d7.js b/docs/assets/js/8c9fcf50.cf3bd3d7.js new file mode 100644 index 0000000000..d515ba1541 --- /dev/null +++ b/docs/assets/js/8c9fcf50.cf3bd3d7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4345],{6744:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.0.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v1.0.x/manual-removal",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v1.0.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v1.0.x/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"ImageList"})," is a cluster-scoped resource and must be called imagelist. ",(0,r.jsx)(n.code,{children:'"*"'})," can be specified to remove all non-running images instead of individual images."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Creating an ",(0,r.jsx)(n.code,{children:"ImageList"})," should trigger an ",(0,r.jsx)(n.code,{children:"ImageJob"})," that will deploy Eraser pods on every node to perform the removal given the list of images."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n"})}),"\n",(0,r.jsx)(n.p,{children:"Pods will run to completion and the images will be removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"ImageList"})," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"Verify the unused images are removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n"})}),"\n",(0,r.jsx)(n.p,{children:"If the image has been successfully removed, there will be no output."})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/8c9fcf50.e1bd2694.js b/docs/assets/js/8c9fcf50.e1bd2694.js deleted file mode 100644 index c5e1e96655..0000000000 --- a/docs/assets/js/8c9fcf50.e1bd2694.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4345],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?l(Object(r),!0).forEach((function(n){a(e,n,r[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))}))}return e}function s(e,n){if(null==e)return{};var r,t,a=function(e,n){if(null==e)return{};var r,t,a={},l=Object.keys(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c<l;c++)o[c]=r[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,r)}u.displayName="MDXCreateElement"},5427:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"version-v1.0.x/manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.0.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v1.0.x/manual-removal",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v1.0.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v1.0.x/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n')),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," is a cluster-scoped resource and must be called imagelist. ",(0,a.kt)("inlineCode",{parentName:"p"},'"*"')," can be specified to remove all non-running images instead of individual images.")),(0,a.kt)("p",null,"Creating an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," should trigger an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageJob")," that will deploy Eraser pods on every node to perform the removal given the list of images."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n")),(0,a.kt)("p",null,"Pods will run to completion and the images will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n")),(0,a.kt)("p",null,"Verify the unused images are removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n")),(0,a.kt)("p",null,"If the image has been successfully removed, there will be no output."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/8cd4fd18.5d94802b.js b/docs/assets/js/8cd4fd18.5d94802b.js new file mode 100644 index 0000000000..a604dbdc66 --- /dev/null +++ b/docs/assets/js/8cd4fd18.5d94802b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1190],{2141:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.0.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v1.0.x/contributing",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v1.0.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v1.0.x/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/8cd4fd18.5dd67d55.js b/docs/assets/js/8cd4fd18.5dd67d55.js deleted file mode 100644 index 12e041a737..0000000000 --- a/docs/assets/js/8cd4fd18.5dd67d55.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1190],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(r),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=r[l];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}d.displayName="MDXCreateElement"},3314:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"version-v1.0.x/contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.0.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v1.0.x/contributing",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v1.0.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v1.0.x/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/8eef7690.687f1101.js b/docs/assets/js/8eef7690.687f1101.js deleted file mode 100644 index b0f0dde7e0..0000000000 --- a/docs/assets/js/8eef7690.687f1101.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[40],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m<l;m++)i[m]=n[m];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}k.displayName="MDXCreateElement"},4488:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"version-v0.5.x/setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v0.5.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v0.5.x/setup",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v0.5.x/customization"},next:{title:"Releasing",permalink:"/eraser/docs/v0.5.x/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-eraser ERASER_IMG=eraser:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n eraser:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-eraser"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-eraser"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/8eef7690.ca5fd282.js b/docs/assets/js/8eef7690.ca5fd282.js new file mode 100644 index 0000000000..7c6b064d14 --- /dev/null +++ b/docs/assets/js/8eef7690.ca5fd282.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[40],{7530:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v0.5.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v0.5.x/setup",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v0.5.x/customization"},next:{title:"Releasing",permalink:"/eraser/docs/v0.5.x/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-eraser ERASER_IMG=eraser:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n eraser:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-eraser"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-eraser"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/8f41530a.3235cd00.js b/docs/assets/js/8f41530a.3235cd00.js deleted file mode 100644 index 5d19f2dbdc..0000000000 --- a/docs/assets/js/8f41530a.3235cd00.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4292],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l<c;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},7137:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"version-v1.1.x/code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.1.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v1.1.x/code-of-conduct",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v1.1.x/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/8f41530a.d1d7746f.js b/docs/assets/js/8f41530a.d1d7746f.js new file mode 100644 index 0000000000..62f9717afb --- /dev/null +++ b/docs/assets/js/8f41530a.d1d7746f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4292],{5093:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>f,frontMatter:()=>d,metadata:()=>i,toc:()=>u});var n=t(5893),c=t(1151);const d={title:"Code of Conduct"},s=void 0,i={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.1.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v1.1.x/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v1.1.x/contributing"}},r={},u=[];function a(e){const o={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["This project has adopted the ",(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"Resources:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:o}={...(0,c.a)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,o,t)=>{t.d(o,{Z:()=>i,a:()=>s});var n=t(7294);const c={},d=n.createContext(c);function s(e){const o=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(d.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/935f2afb.0a68307c.js b/docs/assets/js/935f2afb.0a68307c.js new file mode 100644 index 0000000000..4d3947cdcf --- /dev/null +++ b/docs/assets/js/935f2afb.0a68307c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/next/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/next/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/next/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/next/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/next/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/next/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/next/customization","docId":"customization","unlisted":false},{"type":"link","label":"Metrics","href":"/eraser/docs/next/metrics","docId":"metrics","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/next/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/next/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/next/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/next/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/next/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/next/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/next/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"release-management":{"id":"release-management","title":"Release Management","description":"Overview"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/935f2afb.da0a9203.js b/docs/assets/js/935f2afb.da0a9203.js deleted file mode 100644 index 114c7108ed..0000000000 --- a/docs/assets/js/935f2afb.da0a9203.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[53],{1109:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/next/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/next/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/next/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/next/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/next/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/next/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/next/customization","docId":"customization"},{"type":"link","label":"Metrics","href":"/eraser/docs/next/metrics","docId":"metrics"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/next/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/next/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/next/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/next/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/next/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/next/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/next/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"Overview","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"metrics":{"id":"metrics","title":"Metrics","description":"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the \'eraser-system\' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at \'http8889/metrics\', but a separate exporter can also be configured.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"release-management":{"id":"release-management","title":"Release Management","description":"Overview"},"releasing":{"id":"releasing","title":"Releasing","description":"Create Release Pull Request","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/93bf47d2.597826fd.js b/docs/assets/js/93bf47d2.597826fd.js new file mode 100644 index 0000000000..5e5b82ffb5 --- /dev/null +++ b/docs/assets/js/93bf47d2.597826fd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2288],{9177:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(5893),o=n(1151);const a={title:"Metrics"},s=void 0,i={id:"metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.3.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/metrics",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/customization"},next:{title:"Setup",permalink:"/eraser/docs/setup"}},c={},l=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}];function d(e){const t={a:"a",code:"code",h4:"h4",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,r.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml",children:"otelcollector.yaml"}),", and the endpoint can be specified using the ",(0,r.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options",children:"configmap"}),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at '",(0,r.jsx)(t.a,{href:"http://localhost:8889/metrics",children:"http://localhost:8889/metrics"}),"', but a separate exporter can also be configured."]}),"\n",(0,r.jsx)(t.p,{children:"Below is the list of metrics provided by Eraser per run:"}),"\n",(0,r.jsx)(t.h4,{id:"eraser",children:"Eraser"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n\t- name: images_removed_run_total\n\t\t- description: Total images removed by eraser\n"})}),"\n",(0,r.jsx)(t.h4,{id:"scanner",children:"Scanner"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: vulnerable_images_run_total\n \t- description: Total vulnerable images detected\n"})}),"\n",(0,r.jsx)(t.h4,{id:"imagejob",children:"ImageJob"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: imagejob_run_total\n \t- description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n \t- description: Total pods completed\n - name: pods_failed_run_total\n \t- description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n \t- description: Total time for ImageJobs scheduled to complete\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>i,a:()=>s});var r=n(7294);const o={},a=r.createContext(o);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/93bf47d2.cca23454.js b/docs/assets/js/93bf47d2.cca23454.js deleted file mode 100644 index 07fbf7ff92..0000000000 --- a/docs/assets/js/93bf47d2.cca23454.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2288],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(r),d=o,f=u["".concat(c,".").concat(d)]||u[d]||m[d]||a;return r?n.createElement(f,i(i({ref:t},p),{},{components:r})):n.createElement(f,i({ref:t},p))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s<a;s++)i[s]=r[s];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},3873:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={title:"Metrics"},i=void 0,l={unversionedId:"metrics",id:"version-v1.3.x/metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.3.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/metrics",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/customization"},next:{title:"Setup",permalink:"/eraser/docs/setup"}},c={},s=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}],p={toc:s};function m(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml"},"otelcollector.yaml"),", and the endpoint can be specified using the ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options"},"configmap"),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured."),(0,o.kt)("p",null,"Below is the list of metrics provided by Eraser per run:"),(0,o.kt)("h4",{id:"eraser"},"Eraser"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: images_removed_run_total\n - description: Total images removed by eraser\n")),(0,o.kt)("h4",{id:"scanner"},"Scanner"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: vulnerable_images_run_total\n - description: Total vulnerable images detected\n")),(0,o.kt)("h4",{id:"imagejob"},"ImageJob"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: imagejob_run_total\n - description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n - description: Total pods completed\n - name: pods_failed_run_total\n - description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n - description: Total time for ImageJobs scheduled to complete\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/974203ee.4618b9f3.js b/docs/assets/js/974203ee.4618b9f3.js deleted file mode 100644 index 294999a5e6..0000000000 --- a/docs/assets/js/974203ee.4618b9f3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1351],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var m=a.createContext({}),s=function(e){var t=a.useContext(m),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return a.createElement(m.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,m=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),c=s(n),d=r,g=c["".concat(m,".").concat(d)]||c[d]||u[d]||o;return n?a.createElement(g,l(l({ref:t},p),{},{components:n})):a.createElement(g,l({ref:t},p))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=c;var i={};for(var m in t)hasOwnProperty.call(t,m)&&(i[m]=t[m]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var s=2;s<o;s++)l[s]=n[s];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}c.displayName="MDXCreateElement"},5490:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>m,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const o={title:"Customization"},l=void 0,i={unversionedId:"customization",id:"version-v1.2.x/customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.2.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v1.2.x/customization",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v1.2.x/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/v1.2.x/metrics"}},m={},s=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}],p={toc:s};function u(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl edit configmap --namespace eraser-system eraser-manager-config\n")),(0,r.kt)("p",null,"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."),(0,r.kt)("h2",{id:"key-concepts"},"Key Concepts"),(0,r.kt)("h3",{id:"basic-architecture"},"Basic architecture"),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"manager")," runs as a pod in your cluster and manages ",(0,r.kt)("em",{parentName:"p"},"ImageJobs"),". Think of\nan ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Assessment"),(0,r.kt)("li",{parentName:"ol"},"Removal.")),(0,r.kt)("h3",{id:"scheduling"},"Scheduling"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," can either be created on-demand (see ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/manual-removal"},"Manual Removal"),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."),(0,r.kt)("h3",{id:"fault-tolerance"},"Fault Tolerance"),(0,r.kt)("p",null,"Because an ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.successRatio")," property to\n",(0,r.kt)("inlineCode",{parentName:"p"},"1.0"),". If 75% success sounds good to you, set it to ",(0,r.kt)("inlineCode",{parentName:"p"},"0.75"),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," report success, the job as\na whole will be marked as a failure."),(0,r.kt)("p",null,"This is mainly to help diagnose error conditions. As such, you can set\n",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.cleanup.delayOnFailure")," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."),(0,r.kt)("h3",{id:"excluding-nodes"},"Excluding Nodes"),(0,r.kt)("p",null,"For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter"),", but you can configure the behavior with\nthe options under ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.nodeFilter"),". The ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table")," provides more detail."),(0,r.kt)("h3",{id:"configuring-components"},"Configuring Components"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Collection (What is on the node?)"),(0,r.kt)("li",{parentName:"ol"},"Scanning (What images conform to the policy I've provided?)"),(0,r.kt)("li",{parentName:"ol"},"Removal (Remove images based on the results of the above)")),(0,r.kt)("p",null,"Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,r.kt)("em",{parentName:"p"},"ImageJobs")," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"The collector and/or scanner ",(0,r.kt)("inlineCode",{parentName:"li"},"components")," are enabled, AND"),(0,r.kt)("li",{parentName:"ol"},"The job was ",(0,r.kt)("em",{parentName:"li"},"not")," triggered manually by creating an ",(0,r.kt)("em",{parentName:"li"},"ImageList"),".")),(0,r.kt)("h3",{id:"swapping-out-components"},"Swapping out components"),(0,r.kt)("p",null,"The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.repo")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.tag"),",\nwhere ",(0,r.kt)("inlineCode",{parentName:"p"},"<component>")," is one of ",(0,r.kt)("inlineCode",{parentName:"p"},"collector"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"scanner"),", or ",(0,r.kt)("inlineCode",{parentName:"p"},"remover"),"."),(0,r.kt)("h2",{id:"universal-options"},"Universal Options"),(0,r.kt)("p",null,"The following portions of the configmap apply no matter how you spawn your\n",(0,r.kt)("em",{parentName:"p"},"ImageJob"),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'manager:\n runtime: containerd\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n')),(0,r.kt)("h2",{id:"component-options"},"Component Options"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n")),(0,r.kt)("h2",{id:"scanner-options"},"Scanner Options"),(0,r.kt)("p",null,"These options can be provided to ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.config"),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."),(0,r.kt)("p",null,"Below are the values recognized by the provided ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-trivy-scanner")," image.\nValues provided below are the defaults."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more invormation\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n")),(0,r.kt)("h2",{id:"detailed-options"},"Detailed Options"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Option"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"),(0,r.kt)("th",{parentName:"tr",align:null},"Default"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."),(0,r.kt)("td",{parentName:"tr",align:null},"containerd")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.otlpEndpoint"),(0,r.kt)("td",{parentName:"tr",align:null},"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.logLevel"),(0,r.kt)("td",{parentName:"tr",align:null},"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."),(0,r.kt)("td",{parentName:"tr",align:null},"info")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.repeatInterval"),(0,r.kt)("td",{parentName:"tr",align:null},"Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," at the interval provided."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.beginImmediately"),(0,r.kt)("td",{parentName:"tr",align:null},"If set to true, the fist ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable profiling for the manager's containers. This is for debugging with ",(0,r.kt)("inlineCode",{parentName:"td"},"go tool pprof"),"."),(0,r.kt)("td",{parentName:"tr",align:null},"false")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.port"),(0,r.kt)("td",{parentName:"tr",align:null},"The port on which to expose the profiling endpoint."),(0,r.kt)("td",{parentName:"tr",align:null},"6060")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.successRatio"),(0,r.kt)("td",{parentName:"tr",align:null},"The ratio of successful image jobs required before a cleanup is performed."),(0,r.kt)("td",{parentName:"tr",align:null},"1.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnSuccess"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a successful image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"0s")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnFailure"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a failed image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.pullSecrets"),(0,r.kt)("td",{parentName:"tr",align:null},"The image pull secrets to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.priorityClassName"),(0,r.kt)("td",{parentName:"tr",align:null},"The priority class to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.type"),(0,r.kt)("td",{parentName:"tr",align:null},'The type of node filter to use. Must be either "exclude" or "include".'),(0,r.kt)("td",{parentName:"tr",align:null},"exclude")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.selectors"),(0,r.kt)("td",{parentName:"tr",align:null},"A list of selectors used to filter nodes."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the collector component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/collector")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"7m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the scanner component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/eraser-trivy-scanner")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"1000m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"2Gi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.config"),(0,r.kt)("td",{parentName:"tr",align:null},"The configuration to pass to the scanner container, as a YAML string."),(0,r.kt)("td",{parentName:"tr",align:null},"See YAML below")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/remover")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"0")))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/974203ee.db23a97e.js b/docs/assets/js/974203ee.db23a97e.js new file mode 100644 index 0000000000..cbe9fbbc32 --- /dev/null +++ b/docs/assets/js/974203ee.db23a97e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1351],{946:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var t=r(5893),s=r(1151);const o={title:"Customization"},i=void 0,a={id:"customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.2.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v1.2.x/customization",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v1.2.x/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/v1.2.x/metrics"}},c={},l=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"kubectl edit configmap --namespace eraser-system eraser-manager-config\n"})}),"\n",(0,t.jsx)(n.p,{children:"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."}),"\n",(0,t.jsx)(n.h2,{id:"key-concepts",children:"Key Concepts"}),"\n",(0,t.jsx)(n.h3,{id:"basic-architecture",children:"Basic architecture"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.em,{children:"manager"})," runs as a pod in your cluster and manages ",(0,t.jsx)(n.em,{children:"ImageJobs"}),". Think of\nan ",(0,t.jsx)(n.em,{children:"ImageJob"})," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,t.jsx)(n.em,{children:"ImageJob"})," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Assessment"}),"\n",(0,t.jsx)(n.li,{children:"Removal."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"scheduling",children:"Scheduling"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," can either be created on-demand (see ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/manual-removal",children:"Manual Removal"}),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."]}),"\n",(0,t.jsx)(n.h3,{id:"fault-tolerance",children:"Fault Tolerance"}),"\n",(0,t.jsxs)(n.p,{children:["Because an ",(0,t.jsx)(n.em,{children:"ImageJob"})," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,t.jsx)(n.code,{children:"manager.imageJob.successRatio"})," property to\n",(0,t.jsx)(n.code,{children:"1.0"}),". If 75% success sounds good to you, set it to ",(0,t.jsx)(n.code,{children:"0.75"}),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,t.jsx)(n.em,{children:"ImageJob"})," report success, the job as\na whole will be marked as a failure."]}),"\n",(0,t.jsxs)(n.p,{children:["This is mainly to help diagnose error conditions. As such, you can set\n",(0,t.jsx)(n.code,{children:"manager.imageJob.cleanup.delayOnFailure"})," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."]}),"\n",(0,t.jsx)(n.h3,{id:"excluding-nodes",children:"Excluding Nodes"}),"\n",(0,t.jsxs)(n.p,{children:["For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,t.jsx)(n.code,{children:"eraser.sh/cleanup.filter"}),", but you can configure the behavior with\nthe options under ",(0,t.jsx)(n.code,{children:"manager.nodeFilter"}),". The ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"})," provides more detail."]}),"\n",(0,t.jsx)(n.h3,{id:"configuring-components",children:"Configuring Components"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Collection (What is on the node?)"}),"\n",(0,t.jsx)(n.li,{children:"Scanning (What images conform to the policy I've provided?)"}),"\n",(0,t.jsx)(n.li,{children:"Removal (Remove images based on the results of the above)"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,t.jsx)(n.em,{children:"ImageJobs"})," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["The collector and/or scanner ",(0,t.jsx)(n.code,{children:"components"})," are enabled, AND"]}),"\n",(0,t.jsxs)(n.li,{children:["The job was ",(0,t.jsx)(n.em,{children:"not"})," triggered manually by creating an ",(0,t.jsx)(n.em,{children:"ImageList"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"swapping-out-components",children:"Swapping out components"}),"\n",(0,t.jsxs)(n.p,{children:["The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,t.jsx)(n.code,{children:"components.<component>.image.repo"})," and ",(0,t.jsx)(n.code,{children:"components.<component>.image.tag"}),",\nwhere ",(0,t.jsx)(n.code,{children:"<component>"})," is one of ",(0,t.jsx)(n.code,{children:"collector"}),", ",(0,t.jsx)(n.code,{children:"scanner"}),", or ",(0,t.jsx)(n.code,{children:"remover"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"universal-options",children:"Universal Options"}),"\n",(0,t.jsxs)(n.p,{children:["The following portions of the configmap apply no matter how you spawn your\n",(0,t.jsx)(n.em,{children:"ImageJob"}),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'manager:\n runtime: containerd\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n'})}),"\n",(0,t.jsx)(n.h2,{id:"component-options",children:"Component Options"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n"})}),"\n",(0,t.jsx)(n.h2,{id:"scanner-options",children:"Scanner Options"}),"\n",(0,t.jsxs)(n.p,{children:["These options can be provided to ",(0,t.jsx)(n.code,{children:"components.scanner.config"}),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."]}),"\n",(0,t.jsxs)(n.p,{children:["Below are the values recognized by the provided ",(0,t.jsx)(n.code,{children:"eraser-trivy-scanner"})," image.\nValues provided below are the defaults."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more invormation\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n"})}),"\n",(0,t.jsx)(n.h2,{id:"detailed-options",children:"Detailed Options"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Option"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Default"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.runtime"}),(0,t.jsx)(n.td,{children:"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."}),(0,t.jsx)(n.td,{children:"containerd"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.otlpEndpoint"}),(0,t.jsx)(n.td,{children:"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.logLevel"}),(0,t.jsx)(n.td,{children:"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."}),(0,t.jsx)(n.td,{children:"info"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.repeatInterval"}),(0,t.jsxs)(n.td,{children:["Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,t.jsx)(n.em,{children:"ImageJob"})," at the interval provided."]}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.beginImmediately"}),(0,t.jsxs)(n.td,{children:["If set to true, the fist ",(0,t.jsx)(n.em,{children:"ImageJob"})," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."]}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.enabled"}),(0,t.jsxs)(n.td,{children:["Whether to enable profiling for the manager's containers. This is for debugging with ",(0,t.jsx)(n.code,{children:"go tool pprof"}),"."]}),(0,t.jsx)(n.td,{children:"false"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.port"}),(0,t.jsx)(n.td,{children:"The port on which to expose the profiling endpoint."}),(0,t.jsx)(n.td,{children:"6060"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.successRatio"}),(0,t.jsx)(n.td,{children:"The ratio of successful image jobs required before a cleanup is performed."}),(0,t.jsx)(n.td,{children:"1.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnSuccess"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a successful image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"0s"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnFailure"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a failed image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.pullSecrets"}),(0,t.jsx)(n.td,{children:"The image pull secrets to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.priorityClassName"}),(0,t.jsx)(n.td,{children:"The priority class to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.type"}),(0,t.jsx)(n.td,{children:'The type of node filter to use. Must be either "exclude" or "include".'}),(0,t.jsx)(n.td,{children:"exclude"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.selectors"}),(0,t.jsx)(n.td,{children:"A list of selectors used to filter nodes."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the collector component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the collector image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/collector"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the collector image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the collector container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the collector container."}),(0,t.jsx)(n.td,{children:"7m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the scanner component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the scanner image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the scanner image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the scanner container."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the scanner container."}),(0,t.jsx)(n.td,{children:"1000m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"2Gi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.config"}),(0,t.jsx)(n.td,{children:"The configuration to pass to the scanner container, as a YAML string."}),(0,t.jsx)(n.td,{children:"See YAML below"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the remover image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/remover"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the remover image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the remover container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the remover container."}),(0,t.jsx)(n.td,{children:"0"})]})]})]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>i});var t=r(7294);const s={},o=t.createContext(s);function i(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/9748995c.8c0b6d5e.js b/docs/assets/js/9748995c.8c0b6d5e.js deleted file mode 100644 index 467a7f5985..0000000000 --- a/docs/assets/js/9748995c.8c0b6d5e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8050],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function i(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,o(o({ref:n},p),{},{components:t})):a.createElement(k,o({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,o=new Array(l);o[0]=m;var i={};for(var s in n)hasOwnProperty.call(n,s)&&(i[s]=n[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,o[1]=i;for(var c=2;c<l;c++)o[c]=t[c];return a.createElement.apply(null,o)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},9046:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},o=void 0,i={unversionedId:"quick-start",id:"version-v1.0.x/quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.0.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v1.0.x/quick-start",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v1.0.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v1.0.x/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/v1.0.x/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n")),(0,r.kt)("p",null,"Next, verify that the Pods are running or completed. After the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," Pods complete, you may see a ",(0,r.kt)("inlineCode",{parentName:"p"},"CrashLoopBackoff")," status. This is expected behavior from the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," image and can be ignored for the tutorial."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n")),(0,r.kt)("p",null,"Delete the DaemonSet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl delete daemonset alpine\n")),(0,r.kt)("p",null,"Verify that the Pods have been deleted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNo resources found in default namespace.\n")),(0,r.kt)("p",null,"To verify that the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."),(0,r.kt)("p",null,"List the nodes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.scheduling.repeatInterval")," setting in the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.enabled")," value to ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," using the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". In this case, each collector pod will hold 2 containers: collector and eraser.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/9748995c.9c31807a.js b/docs/assets/js/9748995c.9c31807a.js new file mode 100644 index 0000000000..8661b857e2 --- /dev/null +++ b/docs/assets/js/9748995c.9c31807a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8050],{9393:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>l,metadata:()=>r,toc:()=>c});var t=a(5893),s=a(1151);const l={title:"Quick Start"},i=void 0,r={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.0.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v1.0.x/quick-start",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v1.0.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v1.0.x/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,t.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,t.jsxs)(n.p,{children:["After following the ",(0,t.jsx)(n.a,{href:"/eraser/docs/v1.0.x/installation",children:"install instructions"}),", we'll apply a demo ",(0,t.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,t.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,t.jsxs)(n.p,{children:["First, apply the ",(0,t.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, verify that the Pods are running or completed. After the ",(0,t.jsx)(n.code,{children:"alpine"})," Pods complete, you may see a ",(0,t.jsx)(n.code,{children:"CrashLoopBackoff"})," status. This is expected behavior from the ",(0,t.jsx)(n.code,{children:"alpine"})," image and can be ignored for the tutorial."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n"})}),"\n",(0,t.jsx)(n.p,{children:"Delete the DaemonSet:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl delete daemonset alpine\n"})}),"\n",(0,t.jsx)(n.p,{children:"Verify that the Pods have been deleted:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNo resources found in default namespace.\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To verify that the ",(0,t.jsx)(n.code,{children:"alpine"})," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."]}),"\n",(0,t.jsx)(n.p,{children:"List the nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n"})}),"\n",(0,t.jsxs)(n.p,{children:["List the images then filter for ",(0,t.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,t.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,t.jsx)(n.code,{children:"manager.scheduling.repeatInterval"})," setting in the ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". The default interval is 24 hours (",(0,t.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,t.jsx)(n.p,{children:"Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,t.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,t.jsx)(n.code,{children:"components.scanner.enabled"})," value to ",(0,t.jsx)(n.code,{children:"false"})," using the ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". In this case, each collector pod will hold 2 containers: collector and eraser."]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>r,a:()=>i});var t=a(7294);const s={},l=t.createContext(s);function i(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/99ed3086.1ed71bcf.js b/docs/assets/js/99ed3086.1ed71bcf.js new file mode 100644 index 0000000000..2db2fade0f --- /dev/null +++ b/docs/assets/js/99ed3086.1ed71bcf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5593],{908:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var s=r(5893),t=r(1151);const i={title:"Customization"},o=void 0,a={id:"customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.0.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v1.0.x/customization",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v1.0.x/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/v1.0.x/metrics"}},c={},l=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.p,{children:"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"kubectl edit configmap --namespace eraser-system eraser-manager-config\n"})}),"\n",(0,s.jsx)(n.p,{children:"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."}),"\n",(0,s.jsx)(n.h2,{id:"key-concepts",children:"Key Concepts"}),"\n",(0,s.jsx)(n.h3,{id:"basic-architecture",children:"Basic architecture"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.em,{children:"manager"})," runs as a pod in your cluster and manages ",(0,s.jsx)(n.em,{children:"ImageJobs"}),". Think of\nan ",(0,s.jsx)(n.em,{children:"ImageJob"})," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,s.jsx)(n.em,{children:"ImageJob"})," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Assessment"}),"\n",(0,s.jsx)(n.li,{children:"Removal."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"scheduling",children:"Scheduling"}),"\n",(0,s.jsxs)(n.p,{children:["An ",(0,s.jsx)(n.em,{children:"ImageJob"})," can either be created on-demand (see ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/manual-removal",children:"Manual Removal"}),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."]}),"\n",(0,s.jsx)(n.h3,{id:"fault-tolerance",children:"Fault Tolerance"}),"\n",(0,s.jsxs)(n.p,{children:["Because an ",(0,s.jsx)(n.em,{children:"ImageJob"})," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,s.jsx)(n.code,{children:"manager.imageJob.successRatio"})," property to\n",(0,s.jsx)(n.code,{children:"1.0"}),". If 75% success sounds good to you, set it to ",(0,s.jsx)(n.code,{children:"0.75"}),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,s.jsx)(n.em,{children:"ImageJob"})," report success, the job as\na whole will be marked as a failure."]}),"\n",(0,s.jsxs)(n.p,{children:["This is mainly to help diagnose error conditions. As such, you can set\n",(0,s.jsx)(n.code,{children:"manager.imageJob.cleanup.delayOnFailure"})," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."]}),"\n",(0,s.jsx)(n.h3,{id:"excluding-nodes",children:"Excluding Nodes"}),"\n",(0,s.jsxs)(n.p,{children:["For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,s.jsx)(n.code,{children:"eraser.sh/cleanup.filter"}),", but you can configure the behavior with\nthe options under ",(0,s.jsx)(n.code,{children:"manager.nodeFilter"}),". The ",(0,s.jsx)(n.a,{href:"#detailed-options",children:"table"})," provides more detail."]}),"\n",(0,s.jsx)(n.h3,{id:"configuring-components",children:"Configuring Components"}),"\n",(0,s.jsxs)(n.p,{children:["An ",(0,s.jsx)(n.em,{children:"ImageJob"})," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Collection (What is on the node?)"}),"\n",(0,s.jsx)(n.li,{children:"Scanning (What images conform to the policy I've provided?)"}),"\n",(0,s.jsx)(n.li,{children:"Removal (Remove images based on the results of the above)"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,s.jsx)(n.em,{children:"ImageJobs"})," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["The collector and/or scanner ",(0,s.jsx)(n.code,{children:"components"})," are enabled, AND"]}),"\n",(0,s.jsxs)(n.li,{children:["The job was ",(0,s.jsx)(n.em,{children:"not"})," triggered manually by creating an ",(0,s.jsx)(n.em,{children:"ImageList"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"swapping-out-components",children:"Swapping out components"}),"\n",(0,s.jsxs)(n.p,{children:["The collector, scanner, and eraser components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,s.jsx)(n.code,{children:"components.<component>.image.repo"})," and ",(0,s.jsx)(n.code,{children:"components.<component>.image.tag"}),",\nwhere ",(0,s.jsx)(n.code,{children:"<component>"})," is one of ",(0,s.jsx)(n.code,{children:"collector"}),", ",(0,s.jsx)(n.code,{children:"scanner"}),", or ",(0,s.jsx)(n.code,{children:"eraser"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"universal-options",children:"Universal Options"}),"\n",(0,s.jsxs)(n.p,{children:["The following portions of the configmap apply no matter how you spawn your\n",(0,s.jsx)(n.em,{children:"ImageJob"}),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,s.jsx)(n.a,{href:"#detailed-options",children:"table"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'manager:\n runtime: containerd\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/eraser\n priorityClassName: "" # priority class name for collector/scanner/eraser\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n eraser:\n image:\n repo: ghcr.io/eraser-dev/eraser\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n'})}),"\n",(0,s.jsx)(n.h2,{id:"component-options",children:"Component Options"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n eraser:\n image:\n repo: ghcr.io/eraser-dev/eraser\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n"})}),"\n",(0,s.jsx)(n.h2,{id:"scanner-options",children:"Scanner Options"}),"\n",(0,s.jsxs)(n.p,{children:["These options can be provided to ",(0,s.jsx)(n.code,{children:"components.scanner.config"}),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."]}),"\n",(0,s.jsxs)(n.p,{children:["Below are the values recognized by the provided ",(0,s.jsx)(n.code,{children:"eraser-trivy-scanner"})," image.\nValues provided below are the defaults."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more invormation\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n"})}),"\n",(0,s.jsx)(n.h2,{id:"detailed-options",children:"Detailed Options"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Option"}),(0,s.jsx)(n.th,{children:"Description"}),(0,s.jsx)(n.th,{children:"Default"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.runtime"}),(0,s.jsx)(n.td,{children:"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."}),(0,s.jsx)(n.td,{children:"containerd"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.otlpEndpoint"}),(0,s.jsx)(n.td,{children:"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."}),(0,s.jsx)(n.td,{children:'""'})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.logLevel"}),(0,s.jsx)(n.td,{children:"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."}),(0,s.jsx)(n.td,{children:"info"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.scheduling.repeatInterval"}),(0,s.jsxs)(n.td,{children:["Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,s.jsx)(n.em,{children:"ImageJob"})," at the interval provided."]}),(0,s.jsx)(n.td,{children:"24h"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.scheduling.beginImmediately"}),(0,s.jsxs)(n.td,{children:["If set to true, the fist ",(0,s.jsx)(n.em,{children:"ImageJob"})," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."]}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.profile.enabled"}),(0,s.jsxs)(n.td,{children:["Whether to enable profiling for the manager's containers. This is for debugging with ",(0,s.jsx)(n.code,{children:"go tool pprof"}),"."]}),(0,s.jsx)(n.td,{children:"false"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.profile.port"}),(0,s.jsx)(n.td,{children:"The port on which to expose the profiling endpoint."}),(0,s.jsx)(n.td,{children:"6060"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.imageJob.successRatio"}),(0,s.jsx)(n.td,{children:"The ratio of successful image jobs required before a cleanup is performed."}),(0,s.jsx)(n.td,{children:"1.0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnSuccess"}),(0,s.jsx)(n.td,{children:"The amount of time to wait after a successful image job before performing cleanup."}),(0,s.jsx)(n.td,{children:"0s"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnFailure"}),(0,s.jsx)(n.td,{children:"The amount of time to wait after a failed image job before performing cleanup."}),(0,s.jsx)(n.td,{children:"24h"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.pullSecrets"}),(0,s.jsx)(n.td,{children:"The image pull secrets to use for collector, scanner, and eraser containers."}),(0,s.jsx)(n.td,{children:"[]"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.priorityClassName"}),(0,s.jsx)(n.td,{children:"The priority class to use for collector, scanner, and eraser containers."}),(0,s.jsx)(n.td,{children:'""'})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.nodeFilter.type"}),(0,s.jsx)(n.td,{children:'The type of node filter to use. Must be either "exclude" or "include".'}),(0,s.jsx)(n.td,{children:"exclude"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"manager.nodeFilter.selectors"}),(0,s.jsx)(n.td,{children:"A list of selectors used to filter nodes."}),(0,s.jsx)(n.td,{children:"[]"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.enabled"}),(0,s.jsx)(n.td,{children:"Whether to enable the collector component."}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.image.repo"}),(0,s.jsx)(n.td,{children:"The repository containing the collector image."}),(0,s.jsx)(n.td,{children:"ghcr.io/eraser-dev/collector"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.image.tag"}),(0,s.jsx)(n.td,{children:"The tag of the collector image."}),(0,s.jsx)(n.td,{children:"v1.0.0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.request.mem"}),(0,s.jsx)(n.td,{children:"The amount of memory to request for the collector container."}),(0,s.jsx)(n.td,{children:"25Mi"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.request.cpu"}),(0,s.jsx)(n.td,{children:"The amount of CPU to request for the collector container."}),(0,s.jsx)(n.td,{children:"7m"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.limit.mem"}),(0,s.jsx)(n.td,{children:"The maximum amount of memory the collector container is allowed to use."}),(0,s.jsx)(n.td,{children:"500Mi"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.collector.limit.cpu"}),(0,s.jsx)(n.td,{children:"The maximum amount of CPU the collector container is allowed to use."}),(0,s.jsx)(n.td,{children:"0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.enabled"}),(0,s.jsx)(n.td,{children:"Whether to enable the scanner component."}),(0,s.jsx)(n.td,{children:"true"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.image.repo"}),(0,s.jsx)(n.td,{children:"The repository containing the scanner image."}),(0,s.jsx)(n.td,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.image.tag"}),(0,s.jsx)(n.td,{children:"The tag of the scanner image."}),(0,s.jsx)(n.td,{children:"v1.0.0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.request.mem"}),(0,s.jsx)(n.td,{children:"The amount of memory to request for the scanner container."}),(0,s.jsx)(n.td,{children:"500Mi"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.request.cpu"}),(0,s.jsx)(n.td,{children:"The amount of CPU to request for the scanner container."}),(0,s.jsx)(n.td,{children:"1000m"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.limit.mem"}),(0,s.jsx)(n.td,{children:"The maximum amount of memory the scanner container is allowed to use."}),(0,s.jsx)(n.td,{children:"2Gi"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.limit.cpu"}),(0,s.jsx)(n.td,{children:"The maximum amount of CPU the scanner container is allowed to use."}),(0,s.jsx)(n.td,{children:"0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.scanner.config"}),(0,s.jsx)(n.td,{children:"The configuration to pass to the scanner container, as a YAML string."}),(0,s.jsx)(n.td,{children:"See YAML below"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.eraser.image.repo"}),(0,s.jsx)(n.td,{children:"The repository containing the eraser image."}),(0,s.jsx)(n.td,{children:"ghcr.io/eraser-dev/eraser"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.eraser.image.tag"}),(0,s.jsx)(n.td,{children:"The tag of the eraser image."}),(0,s.jsx)(n.td,{children:"v1.0.0"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.eraser.request.mem"}),(0,s.jsx)(n.td,{children:"The amount of memory to request for the eraser container."}),(0,s.jsx)(n.td,{children:"25Mi"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"components.eraser.request.cpu"}),(0,s.jsx)(n.td,{children:"The amount of CPU to request for the eraser container."}),(0,s.jsx)(n.td,{children:"0"})]})]})]})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>o});var s=r(7294);const t={},i=s.createContext(t);function o(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/99ed3086.694e142d.js b/docs/assets/js/99ed3086.694e142d.js deleted file mode 100644 index 652a224b21..0000000000 --- a/docs/assets/js/99ed3086.694e142d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5593],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),m=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=m(e.components);return a.createElement(s.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=m(n),d=r,g=u["".concat(s,".").concat(d)]||u[d]||c[d]||o;return n?a.createElement(g,l(l({ref:t},p),{},{components:n})):a.createElement(g,l({ref:t},p))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=u;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var m=2;m<o;m++)l[m]=n[m];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}u.displayName="MDXCreateElement"},7223:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>c,frontMatter:()=>o,metadata:()=>i,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const o={title:"Customization"},l=void 0,i={unversionedId:"customization",id:"version-v1.0.x/customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.0.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v1.0.x/customization",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v1.0.x/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/v1.0.x/metrics"}},s={},m=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}],p={toc:m};function c(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl edit configmap --namespace eraser-system eraser-manager-config\n")),(0,r.kt)("p",null,"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."),(0,r.kt)("h2",{id:"key-concepts"},"Key Concepts"),(0,r.kt)("h3",{id:"basic-architecture"},"Basic architecture"),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"manager")," runs as a pod in your cluster and manages ",(0,r.kt)("em",{parentName:"p"},"ImageJobs"),". Think of\nan ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Assessment"),(0,r.kt)("li",{parentName:"ol"},"Removal.")),(0,r.kt)("h3",{id:"scheduling"},"Scheduling"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," can either be created on-demand (see ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/manual-removal"},"Manual Removal"),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."),(0,r.kt)("h3",{id:"fault-tolerance"},"Fault Tolerance"),(0,r.kt)("p",null,"Because an ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.successRatio")," property to\n",(0,r.kt)("inlineCode",{parentName:"p"},"1.0"),". If 75% success sounds good to you, set it to ",(0,r.kt)("inlineCode",{parentName:"p"},"0.75"),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," report success, the job as\na whole will be marked as a failure."),(0,r.kt)("p",null,"This is mainly to help diagnose error conditions. As such, you can set\n",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.cleanup.delayOnFailure")," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."),(0,r.kt)("h3",{id:"excluding-nodes"},"Excluding Nodes"),(0,r.kt)("p",null,"For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter"),", but you can configure the behavior with\nthe options under ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.nodeFilter"),". The ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table")," provides more detail."),(0,r.kt)("h3",{id:"configuring-components"},"Configuring Components"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Collection (What is on the node?)"),(0,r.kt)("li",{parentName:"ol"},"Scanning (What images conform to the policy I've provided?)"),(0,r.kt)("li",{parentName:"ol"},"Removal (Remove images based on the results of the above)")),(0,r.kt)("p",null,"Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,r.kt)("em",{parentName:"p"},"ImageJobs")," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"The collector and/or scanner ",(0,r.kt)("inlineCode",{parentName:"li"},"components")," are enabled, AND"),(0,r.kt)("li",{parentName:"ol"},"The job was ",(0,r.kt)("em",{parentName:"li"},"not")," triggered manually by creating an ",(0,r.kt)("em",{parentName:"li"},"ImageList"),".")),(0,r.kt)("h3",{id:"swapping-out-components"},"Swapping out components"),(0,r.kt)("p",null,"The collector, scanner, and eraser components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.repo")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.tag"),",\nwhere ",(0,r.kt)("inlineCode",{parentName:"p"},"<component>")," is one of ",(0,r.kt)("inlineCode",{parentName:"p"},"collector"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"scanner"),", or ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser"),"."),(0,r.kt)("h2",{id:"universal-options"},"Universal Options"),(0,r.kt)("p",null,"The following portions of the configmap apply no matter how you spawn your\n",(0,r.kt)("em",{parentName:"p"},"ImageJob"),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'manager:\n runtime: containerd\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/eraser\n priorityClassName: "" # priority class name for collector/scanner/eraser\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n eraser:\n image:\n repo: ghcr.io/eraser-dev/eraser\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n')),(0,r.kt)("h2",{id:"component-options"},"Component Options"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n eraser:\n image:\n repo: ghcr.io/eraser-dev/eraser\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n")),(0,r.kt)("h2",{id:"scanner-options"},"Scanner Options"),(0,r.kt)("p",null,"These options can be provided to ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.config"),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."),(0,r.kt)("p",null,"Below are the values recognized by the provided ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-trivy-scanner")," image.\nValues provided below are the defaults."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more invormation\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n")),(0,r.kt)("h2",{id:"detailed-options"},"Detailed Options"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Option"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"),(0,r.kt)("th",{parentName:"tr",align:null},"Default"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."),(0,r.kt)("td",{parentName:"tr",align:null},"containerd")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.otlpEndpoint"),(0,r.kt)("td",{parentName:"tr",align:null},"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.logLevel"),(0,r.kt)("td",{parentName:"tr",align:null},"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."),(0,r.kt)("td",{parentName:"tr",align:null},"info")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.repeatInterval"),(0,r.kt)("td",{parentName:"tr",align:null},"Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," at the interval provided."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.beginImmediately"),(0,r.kt)("td",{parentName:"tr",align:null},"If set to true, the fist ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable profiling for the manager's containers. This is for debugging with ",(0,r.kt)("inlineCode",{parentName:"td"},"go tool pprof"),"."),(0,r.kt)("td",{parentName:"tr",align:null},"false")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.port"),(0,r.kt)("td",{parentName:"tr",align:null},"The port on which to expose the profiling endpoint."),(0,r.kt)("td",{parentName:"tr",align:null},"6060")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.successRatio"),(0,r.kt)("td",{parentName:"tr",align:null},"The ratio of successful image jobs required before a cleanup is performed."),(0,r.kt)("td",{parentName:"tr",align:null},"1.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnSuccess"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a successful image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"0s")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnFailure"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a failed image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.pullSecrets"),(0,r.kt)("td",{parentName:"tr",align:null},"The image pull secrets to use for collector, scanner, and eraser containers."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.priorityClassName"),(0,r.kt)("td",{parentName:"tr",align:null},"The priority class to use for collector, scanner, and eraser containers."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.type"),(0,r.kt)("td",{parentName:"tr",align:null},'The type of node filter to use. Must be either "exclude" or "include".'),(0,r.kt)("td",{parentName:"tr",align:null},"exclude")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.selectors"),(0,r.kt)("td",{parentName:"tr",align:null},"A list of selectors used to filter nodes."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the collector component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/collector")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"7m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the scanner component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/eraser-trivy-scanner")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"1000m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"2Gi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.config"),(0,r.kt)("td",{parentName:"tr",align:null},"The configuration to pass to the scanner container, as a YAML string."),(0,r.kt)("td",{parentName:"tr",align:null},"See YAML below")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.eraser.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the eraser image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/eraser")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.eraser.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the eraser image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.eraser.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the eraser container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.eraser.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the eraser container."),(0,r.kt)("td",{parentName:"tr",align:null},"0")))))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/9d55bf96.47c09e6a.js b/docs/assets/js/9d55bf96.47c09e6a.js deleted file mode 100644 index 0b06247396..0000000000 --- a/docs/assets/js/9d55bf96.47c09e6a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2238],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?o(Object(t),!0).forEach((function(r){i(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):o(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function s(e,r){if(null==e)return{};var t,n,i=function(e,r){if(null==e)return{};var t,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)t=o[n],r.indexOf(t)>=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)t=o[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=n.createContext({}),c=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},p=function(e){var r=c(e.components);return n.createElement(l.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(t),m=i,f=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?n.createElement(f,a(a({ref:r},p),{},{components:t})):n.createElement(f,a({ref:r},p))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var s={};for(var l in r)hasOwnProperty.call(r,l)&&(s[l]=r[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var c=2;c<o;c++)a[c]=t[c];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}d.displayName="MDXCreateElement"},6891:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var n=t(7462),i=(t(7294),t(3905));const o={title:"Exclusion"},a=void 0,s={unversionedId:"exclusion",id:"version-v1.3.x/exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.3.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/exclusion",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/customization"}},l={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],p={toc:c};function u(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the configmap. For more information, see the section on ",(0,i.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization"},"customization"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/9d55bf96.48d408b8.js b/docs/assets/js/9d55bf96.48d408b8.js new file mode 100644 index 0000000000..4fa0da779f --- /dev/null +++ b/docs/assets/js/9d55bf96.48d408b8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2238],{4681:(e,s,i)=>{i.r(s),i.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var r=i(5893),n=i(1151);const t={title:"Exclusion"},o=void 0,a={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.3.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/exclusion",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/customization"}},c={},l=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function d(e){const s={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,n.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,r.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,r.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,r.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,r.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,r.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,r.jsxs)(s.p,{children:["Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,r.jsx)(s.code,{children:"include"})," or ",(0,r.jsx)(s.code,{children:"exclude"})," from the cleanup process using the configmap. For more information, see the section on ",(0,r.jsx)(s.a,{href:"https://eraser-dev.github.io/eraser/docs/customization",children:"customization"}),"."]})]})}function u(e={}){const{wrapper:s}={...(0,n.a)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,s,i)=>{i.d(s,{Z:()=>a,a:()=>o});var r=i(7294);const n={},t=r.createContext(n);function o(e){const s=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/9dbb4f95.67a9bc2d.js b/docs/assets/js/9dbb4f95.67a9bc2d.js new file mode 100644 index 0000000000..c142b5b56b --- /dev/null +++ b/docs/assets/js/9dbb4f95.67a9bc2d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6842],{3553:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.0.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v1.0.x/",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v1.0.x/installation"}},c={},d=[];function l(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/9dbb4f95.ea996f10.js b/docs/assets/js/9dbb4f95.ea996f10.js deleted file mode 100644 index 5b82d6910e..0000000000 --- a/docs/assets/js/9dbb4f95.ea996f10.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6842],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(c,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},7101:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",s={unversionedId:"introduction",id:"version-v1.0.x/introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.0.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v1.0.x/",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v1.0.x/installation"}},c={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/9e350ec0.513719f1.js b/docs/assets/js/9e350ec0.513719f1.js deleted file mode 100644 index fb661bcca5..0000000000 --- a/docs/assets/js/9e350ec0.513719f1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7262],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function o(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function i(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,o(o({ref:n},p),{},{components:t})):a.createElement(k,o({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,o=new Array(l);o[0]=m;var i={};for(var s in n)hasOwnProperty.call(n,s)&&(i[s]=n[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,o[1]=i;for(var c=2;c<l;c++)o[c]=t[c];return a.createElement.apply(null,o)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},6937:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},o=void 0,i={unversionedId:"quick-start",id:"version-v0.4.x/quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v0.4.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v0.4.x/quick-start",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v0.4.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v0.4.x/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/v0.4.x/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n")),(0,r.kt)("p",null,"Next, verify that the Pods are running or completed. After the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," Pods complete, you may see a ",(0,r.kt)("inlineCode",{parentName:"p"},"CrashLoopBackoff")," status. This is expected behavior from the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," image and can be ignored for the tutorial."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n")),(0,r.kt)("p",null,"Delete the DaemonSet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl delete daemonset alpine\n")),(0,r.kt)("p",null,"Verify that the Pods have been deleted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNo resources found in default namespace.\n")),(0,r.kt)("p",null,"To verify that the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."),(0,r.kt)("p",null,"List the nodes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by ",(0,r.kt)("inlineCode",{parentName:"p"},"--repeat-period")," argument to ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-controller-manager"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by removing the ",(0,r.kt)("inlineCode",{parentName:"p"},"--scanner-image")," argument. If you are deploying with Helm, use ",(0,r.kt)("inlineCode",{parentName:"p"},'--set scanner.image.repository=""')," to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/9e350ec0.5d832f0e.js b/docs/assets/js/9e350ec0.5d832f0e.js new file mode 100644 index 0000000000..35eb17f066 --- /dev/null +++ b/docs/assets/js/9e350ec0.5d832f0e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7262],{9295:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>i,toc:()=>c});var t=a(5893),s=a(1151);const l={title:"Quick Start"},r=void 0,i={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v0.4.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v0.4.x/quick-start",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v0.4.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v0.4.x/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,t.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,t.jsxs)(n.p,{children:["After following the ",(0,t.jsx)(n.a,{href:"/eraser/docs/v0.4.x/installation",children:"install instructions"}),", we'll apply a demo ",(0,t.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,t.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,t.jsxs)(n.p,{children:["First, apply the ",(0,t.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Next, verify that the Pods are running or completed. After the ",(0,t.jsx)(n.code,{children:"alpine"})," Pods complete, you may see a ",(0,t.jsx)(n.code,{children:"CrashLoopBackoff"})," status. This is expected behavior from the ",(0,t.jsx)(n.code,{children:"alpine"})," image and can be ignored for the tutorial."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n"})}),"\n",(0,t.jsx)(n.p,{children:"Delete the DaemonSet:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl delete daemonset alpine\n"})}),"\n",(0,t.jsx)(n.p,{children:"Verify that the Pods have been deleted:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNo resources found in default namespace.\n"})}),"\n",(0,t.jsxs)(n.p,{children:["To verify that the ",(0,t.jsx)(n.code,{children:"alpine"})," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."]}),"\n",(0,t.jsx)(n.p,{children:"List the nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n"})}),"\n",(0,t.jsxs)(n.p,{children:["List the images then filter for ",(0,t.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,t.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,t.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by ",(0,t.jsx)(n.code,{children:"--repeat-period"})," argument to ",(0,t.jsx)(n.code,{children:"eraser-controller-manager"}),". The default interval is 24 hours (",(0,t.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,t.jsx)(n.p,{children:"Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,t.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by removing the ",(0,t.jsx)(n.code,{children:"--scanner-image"})," argument. If you are deploying with Helm, use ",(0,t.jsx)(n.code,{children:'--set scanner.image.repository=""'})," to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser."]}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>i,a:()=>r});var t=a(7294);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/9ff53b5b.5c60e5b7.js b/docs/assets/js/9ff53b5b.5c60e5b7.js deleted file mode 100644 index 7a56c2e226..0000000000 --- a/docs/assets/js/9ff53b5b.5c60e5b7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9829],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,c(c({ref:t},p),{},{components:n})):r.createElement(f,c({ref:t},p))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var l=2;l<o;l++)c[l]=n[l];return r.createElement.apply(null,c)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},4129:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const o={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"version-v1.3.x/custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.3.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/custom-scanner",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],p={toc:l};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,a.kt)("p",null,"To create a custom scanner for non-compliant images, use the following ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser-scanner-template/"},"template"),"."),(0,a.kt)("p",null,"In order to customize your scanner, start by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},"NewImageProvider()"),". The ImageProvider interface can be found can be found ",(0,a.kt)("a",{parentName:"p",href:"../../pkg/scanners/template/scanner_template.go"},"here"),". "),(0,a.kt)("p",null,"The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,a.kt)("inlineCode",{parentName:"p"},"ReceiveImages()")," function. Process these images with your customized scanner and threshold, and use ",(0,a.kt)("inlineCode",{parentName:"p"},"SendImages()")," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,a.kt)("inlineCode",{parentName:"p"},"Finish()"),"."),(0,a.kt)("p",null,"When complete, provide your custom scanner image to Eraser in deployment."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/9ff53b5b.7090781c.js b/docs/assets/js/9ff53b5b.7090781c.js new file mode 100644 index 0000000000..b9b3ed8737 --- /dev/null +++ b/docs/assets/js/9ff53b5b.7090781c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9829],{8595:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var r=t(5893),s=t(1151);const o={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.3.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/trivy"}},i={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsxs)(n.p,{children:["To create a custom scanner for non-compliant images, use the following ",(0,r.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser-scanner-template/",children:"template"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In order to customize your scanner, start by creating a ",(0,r.jsx)(n.code,{children:"NewImageProvider()"}),". The ImageProvider interface can be found can be found ",(0,r.jsx)(n.a,{href:"../../pkg/scanners/template/scanner_template.go",children:"here"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,r.jsx)(n.code,{children:"ReceiveImages()"})," function. Process these images with your customized scanner and threshold, and use ",(0,r.jsx)(n.code,{children:"SendImages()"})," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,r.jsx)(n.code,{children:"Finish()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"When complete, provide your custom scanner image to Eraser in deployment."})]})}function u(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const s={},o=r.createContext(s);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/a09c2993.479588b5.js b/docs/assets/js/a09c2993.479588b5.js deleted file mode 100644 index 9b5922c6ff..0000000000 --- a/docs/assets/js/a09c2993.479588b5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4128],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},8495:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",c={unversionedId:"introduction",id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/docs/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/next/",draft:!1,tags:[],version:"current",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/next/installation"}},s={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/a09c2993.9909da7a.js b/docs/assets/js/a09c2993.9909da7a.js new file mode 100644 index 0000000000..ab2fc2c7b5 --- /dev/null +++ b/docs/assets/js/a09c2993.9909da7a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4128],{2214:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>l});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/docs/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/next/",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/next/installation"}},c={},l=[];function d(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/a683e47f.6b48266e.js b/docs/assets/js/a683e47f.6b48266e.js new file mode 100644 index 0000000000..8b9a368016 --- /dev/null +++ b/docs/assets/js/a683e47f.6b48266e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[846],{828:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>h,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var s=i(5893),r=i(1151);const t={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Overview",source:"@site/versioned_docs/version-v0.5.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v0.5.x/releasing",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v0.5.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v0.5.x/custom-scanner"}},o={},c=[{value:"Overview",id:"overview",level:2},{value:"Versioning",id:"versioning",level:2},{value:"Building and releasing",id:"building-and-releasing",level:2},{value:"Publishing",id:"publishing",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.p,{children:"The release process consists of three phases: versioning, building, and publishing."}),"\n",(0,s.jsx)(n.p,{children:"Versioning involves maintaining the following files:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Makefile"})," - the Makefile contains a VERSION variable that defines the version of the project."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"manager.yaml"})," - the controller-manager deployment yaml contains the latest release tag image of the project."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"eraser.yaml"})," - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release."}),"\n",(0,s.jsx)(n.p,{children:"Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline."}),"\n",(0,s.jsxs)(n.p,{children:["Publishing involves creating a release tag and creating a new ",(0,s.jsx)(n.em,{children:"Release"})," on GitHub."]}),"\n",(0,s.jsx)(n.h2,{id:"versioning",children:"Versioning"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Obtain a copy of the repository."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git clone git@github.com:eraser-dev/eraser.git\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If this is a patch release for a release branch, check out applicable branch, such as ",(0,s.jsx)(n.code,{children:"release-0.1"}),". If not, branch should be ",(0,s.jsx)(n.code,{children:"main"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Execute the release-patch target to generate patch. Give the semantic version of the release:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make release-manifest NEWVERSION=vX.Y.Z\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Promote staging manifest to release."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make promote-staging-manifest\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["If it's a new minor release (e.g. v0.",(0,s.jsx)(n.strong,{children:"4"}),".x -> 0.",(0,s.jsx)(n.strong,{children:"5"}),".0), tag docs to be versioned. Make sure to keep patch version as ",(0,s.jsx)(n.code,{children:".x"})," for a minor release."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"make version-docs NEWVERSION=v0.5.x\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Preview the changes:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git status\ngit diff\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"building-and-releasing",children:"Building and releasing"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Commit the changes and push to remote repository to create a pull request."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'git checkout -b release-<NEW VERSION>\ngit commit -a -s -m "Prepare <NEW VERSION> release"\ngit push <YOUR FORK>\n'})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Once the PR is merged to ",(0,s.jsx)(n.code,{children:"main"})," or ",(0,s.jsx)(n.code,{children:"release"})," branch (",(0,s.jsx)(n.code,{children:"<BRANCH NAME>"})," below), tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(n.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser"})," and ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser-manager"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,i)=>{i.d(n,{Z:()=>a,a:()=>l});var s=i(7294);const r={},t=s.createContext(r);function l(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/a683e47f.b8f20d95.js b/docs/assets/js/a683e47f.b8f20d95.js deleted file mode 100644 index 1ce7909c34..0000000000 --- a/docs/assets/js/a683e47f.b8f20d95.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[846],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>g});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),p=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},c=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),u=p(r),g=a,d=u["".concat(s,".").concat(g)]||u[g]||m[g]||i;return r?n.createElement(d,l(l({ref:t},c),{},{components:r})):n.createElement(d,l({ref:t},c))}));function g(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=u;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var p=2;p<i;p++)l[p]=r[p];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},1805:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>m,frontMatter:()=>i,metadata:()=>o,toc:()=>p});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"version-v0.5.x/releasing",title:"Releasing",description:"Overview",source:"@site/versioned_docs/version-v0.5.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v0.5.x/releasing",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v0.5.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v0.5.x/custom-scanner"}},s={},p=[{value:"Overview",id:"overview",level:2},{value:"Versioning",id:"versioning",level:2},{value:"Building and releasing",id:"building-and-releasing",level:2},{value:"Publishing",id:"publishing",level:2}],c={toc:p};function m(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"overview"},"Overview"),(0,a.kt)("p",null,"The release process consists of three phases: versioning, building, and publishing."),(0,a.kt)("p",null,"Versioning involves maintaining the following files:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"Makefile")," - the Makefile contains a VERSION variable that defines the version of the project."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"manager.yaml")," - the controller-manager deployment yaml contains the latest release tag image of the project."),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("strong",{parentName:"li"},"eraser.yaml")," - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project.")),(0,a.kt)("p",null,"The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release."),(0,a.kt)("p",null,"Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline."),(0,a.kt)("p",null,"Publishing involves creating a release tag and creating a new ",(0,a.kt)("em",{parentName:"p"},"Release")," on GitHub."),(0,a.kt)("h2",{id:"versioning"},"Versioning"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Obtain a copy of the repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git clone git@github.com:eraser-dev/eraser.git\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"If this is a patch release for a release branch, check out applicable branch, such as ",(0,a.kt)("inlineCode",{parentName:"p"},"release-0.1"),". If not, branch should be ",(0,a.kt)("inlineCode",{parentName:"p"},"main"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Execute the release-patch target to generate patch. Give the semantic version of the release:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"make release-manifest NEWVERSION=vX.Y.Z\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Promote staging manifest to release."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"make promote-staging-manifest\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"If it's a new minor release (e.g. v0.",(0,a.kt)("strong",{parentName:"p"},"4"),".x -> 0.",(0,a.kt)("strong",{parentName:"p"},"5"),".0), tag docs to be versioned. Make sure to keep patch version as ",(0,a.kt)("inlineCode",{parentName:"p"},".x")," for a minor release."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"make version-docs NEWVERSION=v0.5.x\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Preview the changes:"),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git status\ngit diff\n")))),(0,a.kt)("h2",{id:"building-and-releasing"},"Building and releasing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Commit the changes and push to remote repository to create a pull request."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},'git checkout -b release-<NEW VERSION>\ngit commit -a -s -m "Prepare <NEW VERSION> release"\ngit push <YOUR FORK>\n'))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main")," or ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," branch (",(0,a.kt)("inlineCode",{parentName:"p"},"<BRANCH NAME>")," below), tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/a708fa78.2bb257f2.js b/docs/assets/js/a708fa78.2bb257f2.js deleted file mode 100644 index f79fdf68c3..0000000000 --- a/docs/assets/js/a708fa78.2bb257f2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2356],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l<c;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},2472:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"version-v1.2.x/code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.2.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v1.2.x/code-of-conduct",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v1.2.x/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/a708fa78.54aaa7fc.js b/docs/assets/js/a708fa78.54aaa7fc.js new file mode 100644 index 0000000000..ba1868195b --- /dev/null +++ b/docs/assets/js/a708fa78.54aaa7fc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2356],{7109:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>f,frontMatter:()=>d,metadata:()=>i,toc:()=>u});var n=t(5893),c=t(1151);const d={title:"Code of Conduct"},s=void 0,i={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.2.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v1.2.x/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v1.2.x/contributing"}},r={},u=[];function a(e){const o={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["This project has adopted the ",(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"Resources:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:o}={...(0,c.a)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,o,t)=>{t.d(o,{Z:()=>i,a:()=>s});var n=t(7294);const c={},d=n.createContext(c);function s(e){const o=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(d.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/a7bd4aaa.45274bc2.js b/docs/assets/js/a7bd4aaa.45274bc2.js new file mode 100644 index 0000000000..ea2bd3e183 --- /dev/null +++ b/docs/assets/js/a7bd4aaa.45274bc2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8518],{8564:(e,n,s)=>{s.r(n),s.d(n,{default:()=>d});s(7294);var r=s(833),o=s(3320),t=s(4477),i=s(8790),c=s(197),u=s(5893);function a(e){const{version:n}=e;return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(c.Z,{version:n.version,tag:(0,o.os)(n.pluginId,n.version)}),(0,u.jsx)(r.d,{children:n.noIndex&&(0,u.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function l(e){const{version:n,route:s}=e;return(0,u.jsx)(r.FG,{className:n.className,children:(0,u.jsx)(t.q,{version:n,children:(0,i.H)(s.routes)})})}function d(e){return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(a,{...e}),(0,u.jsx)(l,{...e})]})}}}]); \ No newline at end of file diff --git a/docs/assets/js/a8f67d08.9df77a9f.js b/docs/assets/js/a8f67d08.9df77a9f.js new file mode 100644 index 0000000000..131f3d0abb --- /dev/null +++ b/docs/assets/js/a8f67d08.9df77a9f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7591],{1228:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.2.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v1.2.x/contributing",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v1.2.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v1.2.x/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/a8f67d08.d837a742.js b/docs/assets/js/a8f67d08.d837a742.js deleted file mode 100644 index 372303f20e..0000000000 --- a/docs/assets/js/a8f67d08.d837a742.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7591],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(r),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=r[l];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}d.displayName="MDXCreateElement"},4157:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"version-v1.2.x/contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.2.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v1.2.x/contributing",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v1.2.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v1.2.x/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/a932041a.2d3e796f.js b/docs/assets/js/a932041a.2d3e796f.js new file mode 100644 index 0000000000..0830e92934 --- /dev/null +++ b/docs/assets/js/a932041a.2d3e796f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5754],{3364:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v0.4.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v0.4.x/setup",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v0.4.x/customization"},next:{title:"Releasing",permalink:"/eraser/docs/v0.4.x/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-eraser ERASER_IMG=eraser:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n eraser:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-eraser"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-eraser"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ERASER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/a932041a.d5e014b0.js b/docs/assets/js/a932041a.d5e014b0.js deleted file mode 100644 index 01377313d1..0000000000 --- a/docs/assets/js/a932041a.d5e014b0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5754],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m<l;m++)i[m]=n[m];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}k.displayName="MDXCreateElement"},4906:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"version-v0.4.x/setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v0.4.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/v0.4.x/setup",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v0.4.x/customization"},next:{title:"Releasing",permalink:"/eraser/docs/v0.4.x/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-eraser ERASER_IMG=eraser:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n eraser:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-eraser"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-eraser"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ERASER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/a94703ab.5018fc8a.js b/docs/assets/js/a94703ab.5018fc8a.js new file mode 100644 index 0000000000..f2f44961c5 --- /dev/null +++ b/docs/assets/js/a94703ab.5018fc8a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4368],{2674:(e,t,n)=>{n.r(t),n.d(t,{default:()=>be});var a=n(7294),o=n(512),i=n(833),s=n(5281),l=n(2802),r=n(1116),c=n(5999),d=n(2466),u=n(5936);const m={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};var b=n(5893);function h(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),i=(0,a.useRef)(!1),{startScroll:s,cancelScroll:l}=(0,d.Ct)();return(0,d.RF)(((e,n)=>{let{scrollY:a}=e;const s=n?.scrollY;s&&(i.current?i.current=!1:a>=s?(l(),o(!1)):a<t?o(!1):a+window.innerHeight<document.documentElement.scrollHeight&&o(!0))})),(0,u.S)((e=>{e.location.hash&&(i.current=!0,o(!1))})),{shown:n,scrollToTop:()=>s(0)}}({threshold:300});return(0,b.jsx)("button",{"aria-label":(0,c.I)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.Z)("clean-btn",s.k.common.backToTopButton,m.backToTopButton,e&&m.backToTopButtonShow),type:"button",onClick:t})}var p=n(1442),x=n(6550),f=n(7524),j=n(6668),k=n(1327);function _(e){return(0,b.jsx)("svg",{width:"20",height:"20","aria-hidden":"true",...e,children:(0,b.jsxs)("g",{fill:"#7a7a7a",children:[(0,b.jsx)("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),(0,b.jsx)("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})]})})}const v={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function g(e){let{onClick:t}=e;return(0,b.jsx)("button",{type:"button",title:(0,c.I)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,c.I)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.Z)("button button--secondary button--outline",v.collapseSidebarButton),onClick:t,children:(0,b.jsx)(_,{className:v.collapseSidebarButtonIcon})})}var C=n(9689),S=n(902);const I=Symbol("EmptyContext"),N=a.createContext(I);function T(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),i=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return(0,b.jsx)(N.Provider,{value:i,children:t})}var B=n(6043),Z=n(8596),A=n(3692),L=n(2389);function y(e){let{collapsed:t,categoryLabel:n,onClick:a}=e;return(0,b.jsx)("button",{"aria-label":t?(0,c.I)({id:"theme.DocSidebarItem.expandCategoryAriaLabel",message:"Expand sidebar category '{label}'",description:"The ARIA label to expand the sidebar category"},{label:n}):(0,c.I)({id:"theme.DocSidebarItem.collapseCategoryAriaLabel",message:"Collapse sidebar category '{label}'",description:"The ARIA label to collapse the sidebar category"},{label:n}),type:"button",className:"clean-btn menu__caret",onClick:a})}function w(e){let{item:t,onItemClick:n,activePath:i,level:r,index:c,...d}=e;const{items:u,label:m,collapsible:h,className:p,href:x}=t,{docs:{sidebar:{autoCollapseCategories:f}}}=(0,j.L)(),k=function(e){const t=(0,L.Z)();return(0,a.useMemo)((()=>e.href&&!e.linkUnlisted?e.href:!t&&e.collapsible?(0,l.LM)(e):void 0),[e,t])}(t),_=(0,l._F)(t,i),v=(0,Z.Mg)(x,i),{collapsed:g,setCollapsed:C}=(0,B.u)({initialState:()=>!!h&&(!_&&t.collapsed)}),{expandedItem:T,setExpandedItem:w}=function(){const e=(0,a.useContext)(N);if(e===I)throw new S.i6("DocSidebarItemsExpandedStateProvider");return e}(),E=function(e){void 0===e&&(e=!g),w(e?null:c),C(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const i=(0,S.D9)(t);(0,a.useEffect)((()=>{t&&!i&&n&&o(!1)}),[t,i,n,o])}({isActive:_,collapsed:g,updateCollapsed:E}),(0,a.useEffect)((()=>{h&&null!=T&&T!==c&&f&&C(!0)}),[h,T,c,C,f]),(0,b.jsxs)("li",{className:(0,o.Z)(s.k.docs.docSidebarItemCategory,s.k.docs.docSidebarItemCategoryLevel(r),"menu__list-item",{"menu__list-item--collapsed":g},p),children:[(0,b.jsxs)("div",{className:(0,o.Z)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":v}),children:[(0,b.jsx)(A.Z,{className:(0,o.Z)("menu__link",{"menu__link--sublist":h,"menu__link--sublist-caret":!x&&h,"menu__link--active":_}),onClick:h?e=>{n?.(t),x?E(!1):(e.preventDefault(),E())}:()=>{n?.(t)},"aria-current":v?"page":void 0,"aria-expanded":h?!g:void 0,href:h?k??"#":k,...d,children:m}),x&&h&&(0,b.jsx)(y,{collapsed:g,categoryLabel:m,onClick:e=>{e.preventDefault(),E()}})]}),(0,b.jsx)(B.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:g,children:(0,b.jsx)(V,{items:u,tabIndex:g?-1:0,onItemClick:n,activePath:i,level:r+1})})]})}var E=n(3919),H=n(9471);const M={menuExternalLink:"menuExternalLink_NmtK"};function R(e){let{item:t,onItemClick:n,activePath:a,level:i,index:r,...c}=e;const{href:d,label:u,className:m,autoAddBaseUrl:h}=t,p=(0,l._F)(t,a),x=(0,E.Z)(d);return(0,b.jsx)("li",{className:(0,o.Z)(s.k.docs.docSidebarItemLink,s.k.docs.docSidebarItemLinkLevel(i),"menu__list-item",m),children:(0,b.jsxs)(A.Z,{className:(0,o.Z)("menu__link",!x&&M.menuExternalLink,{"menu__link--active":p}),autoAddBaseUrl:h,"aria-current":p?"page":void 0,to:d,...x&&{onClick:n?()=>n(t):void 0},...c,children:[u,!x&&(0,b.jsx)(H.Z,{})]})},u)}const W={menuHtmlItem:"menuHtmlItem_M9Kj"};function F(e){let{item:t,level:n,index:a}=e;const{value:i,defaultStyle:l,className:r}=t;return(0,b.jsx)("li",{className:(0,o.Z)(s.k.docs.docSidebarItemLink,s.k.docs.docSidebarItemLinkLevel(n),l&&[W.menuHtmlItem,"menu__list-item"],r),dangerouslySetInnerHTML:{__html:i}},a)}function P(e){let{item:t,...n}=e;switch(t.type){case"category":return(0,b.jsx)(w,{item:t,...n});case"html":return(0,b.jsx)(F,{item:t,...n});default:return(0,b.jsx)(R,{item:t,...n})}}function D(e){let{items:t,...n}=e;const a=(0,l.f)(t,n.activePath);return(0,b.jsx)(T,{children:a.map(((e,t)=>(0,b.jsx)(P,{item:e,index:t,...n},t)))})}const V=(0,a.memo)(D),U={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function K(e){let{path:t,sidebar:n,className:i}=e;const l=function(){const{isActive:e}=(0,C.nT)(),[t,n]=(0,a.useState)(e);return(0,d.RF)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return(0,b.jsx)("nav",{"aria-label":(0,c.I)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.Z)("menu thin-scrollbar",U.menu,l&&U.menuWithAnnouncementBar,i),children:(0,b.jsx)("ul",{className:(0,o.Z)(s.k.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(V,{items:n,activePath:t,level:1})})})}const Y="sidebar_njMd",z="sidebarWithHideableNavbar_wUlq",G="sidebarHidden_VK0M",O="sidebarLogo_isFc";function q(e){let{path:t,sidebar:n,onCollapse:a,isHidden:i}=e;const{navbar:{hideOnScroll:s},docs:{sidebar:{hideable:l}}}=(0,j.L)();return(0,b.jsxs)("div",{className:(0,o.Z)(Y,s&&z,i&&G),children:[s&&(0,b.jsx)(k.Z,{tabIndex:-1,className:O}),(0,b.jsx)(K,{path:t,sidebar:n}),l&&(0,b.jsx)(g,{onClick:a})]})}const J=a.memo(q);var Q=n(3102),X=n(3163);const $=e=>{let{sidebar:t,path:n}=e;const a=(0,X.e)();return(0,b.jsx)("ul",{className:(0,o.Z)(s.k.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(V,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&a.toggle(),"link"===e.type&&a.toggle()},level:1})})};function ee(e){return(0,b.jsx)(Q.Zo,{component:$,props:e})}const te=a.memo(ee);function ne(e){const t=(0,f.i)(),n="desktop"===t||"ssr"===t,a="mobile"===t;return(0,b.jsxs)(b.Fragment,{children:[n&&(0,b.jsx)(J,{...e}),a&&(0,b.jsx)(te,{...e})]})}const ae={expandButton:"expandButton_TmdG",expandButtonIcon:"expandButtonIcon_i1dp"};function oe(e){let{toggleSidebar:t}=e;return(0,b.jsx)("div",{className:ae.expandButton,title:(0,c.I)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,c.I)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t,children:(0,b.jsx)(_,{className:ae.expandButtonIcon})})}const ie={docSidebarContainer:"docSidebarContainer_YfHR",docSidebarContainerHidden:"docSidebarContainerHidden_DPk8",sidebarViewport:"sidebarViewport_aRkj"};function se(e){let{children:t}=e;const n=(0,r.V)();return(0,b.jsx)(a.Fragment,{children:t},n?.name??"noSidebar")}function le(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:i}=e;const{pathname:l}=(0,x.TH)(),[r,c]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{r&&c(!1),!r&&(0,p.n)()&&c(!0),i((e=>!e))}),[i,r]);return(0,b.jsx)("aside",{className:(0,o.Z)(s.k.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&c(!0)},children:(0,b.jsx)(se,{children:(0,b.jsxs)("div",{className:(0,o.Z)(ie.sidebarViewport,r&&ie.sidebarViewportHidden),children:[(0,b.jsx)(ne,{sidebar:t,path:l,onCollapse:d,isHidden:r}),r&&(0,b.jsx)(oe,{toggleSidebar:d})]})})})}const re={docMainContainer:"docMainContainer_TBSr",docMainContainerEnhanced:"docMainContainerEnhanced_lQrH",docItemWrapperEnhanced:"docItemWrapperEnhanced_JWYK"};function ce(e){let{hiddenSidebarContainer:t,children:n}=e;const a=(0,r.V)();return(0,b.jsx)("main",{className:(0,o.Z)(re.docMainContainer,(t||!a)&&re.docMainContainerEnhanced),children:(0,b.jsx)("div",{className:(0,o.Z)("container padding-top--md padding-bottom--lg",re.docItemWrapper,t&&re.docItemWrapperEnhanced),children:n})})}const de={docRoot:"docRoot_UBD9",docsWrapper:"docsWrapper_hBAB"};function ue(e){let{children:t}=e;const n=(0,r.V)(),[o,i]=(0,a.useState)(!1);return(0,b.jsxs)("div",{className:de.docsWrapper,children:[(0,b.jsx)(h,{}),(0,b.jsxs)("div",{className:de.docRoot,children:[n&&(0,b.jsx)(le,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:i}),(0,b.jsx)(ce,{hiddenSidebarContainer:o,children:t})]})]})}var me=n(5658);function be(e){const t=(0,l.SN)(e);if(!t)return(0,b.jsx)(me.Z,{});const{docElement:n,sidebarName:a,sidebarItems:c}=t;return(0,b.jsx)(i.FG,{className:(0,o.Z)(s.k.page.docsDocPage),children:(0,b.jsx)(r.b,{name:a,items:c,children:(0,b.jsx)(ue,{children:n})})})}},5658:(e,t,n)=>{n.d(t,{Z:()=>l});n(7294);var a=n(512),o=n(5999),i=n(2503),s=n(5893);function l(e){let{className:t}=e;return(0,s.jsx)("main",{className:(0,a.Z)("container margin-vert--xl",t),children:(0,s.jsx)("div",{className:"row",children:(0,s.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,s.jsx)(i.Z,{as:"h1",className:"hero__title",children:(0,s.jsx)(o.Z,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.Z,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.Z,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]); \ No newline at end of file diff --git a/docs/assets/js/ae417a11.3d424f98.js b/docs/assets/js/ae417a11.3d424f98.js new file mode 100644 index 0000000000..8b2b239c37 --- /dev/null +++ b/docs/assets/js/ae417a11.3d424f98.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6300],{4590:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var s=a(5893),t=a(1151);const r={title:"Quick Start"},i=void 0,l={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.3.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/quick-start",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/installation"},next:{title:"Architecture",permalink:"/eraser/docs/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,s.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,s.jsxs)(n.p,{children:["After following the ",(0,s.jsx)(n.a,{href:"/eraser/docs/installation",children:"install instructions"}),", we'll apply a demo ",(0,s.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,s.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,s.jsxs)(n.p,{children:["First, apply the ",(0,s.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Next, verify that the Pods are running or completed. After the ",(0,s.jsx)(n.code,{children:"alpine"})," Pods complete, you may see a ",(0,s.jsx)(n.code,{children:"CrashLoopBackoff"})," status. This is expected behavior from the ",(0,s.jsx)(n.code,{children:"alpine"})," image and can be ignored for the tutorial."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n"})}),"\n",(0,s.jsx)(n.p,{children:"Delete the DaemonSet:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl delete daemonset alpine\n"})}),"\n",(0,s.jsx)(n.p,{children:"Verify that the Pods have been deleted:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNo resources found in default namespace.\n"})}),"\n",(0,s.jsxs)(n.p,{children:["To verify that the ",(0,s.jsx)(n.code,{children:"alpine"})," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."]}),"\n",(0,s.jsx)(n.p,{children:"List the nodes:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n"})}),"\n",(0,s.jsxs)(n.p,{children:["List the images then filter for ",(0,s.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,s.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,s.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,s.jsx)(n.code,{children:"manager.scheduling.repeatInterval"})," setting in the ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". The default interval is 24 hours (",(0,s.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,s.jsx)(n.p,{children:"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,s.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,s.jsx)(n.code,{children:"components.scanner.enabled"})," value to ",(0,s.jsx)(n.code,{children:"false"})," using the ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". In this case, each collector pod will hold 2 containers: collector and remover."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>l,a:()=>i});var s=a(7294);const t={},r=s.createContext(t);function i(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ae417a11.d3ca84d8.js b/docs/assets/js/ae417a11.d3ca84d8.js deleted file mode 100644 index 94608fec1f..0000000000 --- a/docs/assets/js/ae417a11.d3ca84d8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6300],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function o(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,i(i({ref:n},p),{},{components:t})):a.createElement(k,i({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,i=new Array(l);i[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var c=2;c<l;c++)i[c]=t[c];return a.createElement.apply(null,i)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},3386:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},i=void 0,o={unversionedId:"quick-start",id:"version-v1.3.x/quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.3.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/quick-start",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/installation"},next:{title:"Architecture",permalink:"/eraser/docs/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n")),(0,r.kt)("p",null,"Next, verify that the Pods are running or completed. After the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," Pods complete, you may see a ",(0,r.kt)("inlineCode",{parentName:"p"},"CrashLoopBackoff")," status. This is expected behavior from the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," image and can be ignored for the tutorial."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n")),(0,r.kt)("p",null,"Delete the DaemonSet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl delete daemonset alpine\n")),(0,r.kt)("p",null,"Verify that the Pods have been deleted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNo resources found in default namespace.\n")),(0,r.kt)("p",null,"To verify that the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."),(0,r.kt)("p",null,"List the nodes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.scheduling.repeatInterval")," setting in the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.enabled")," value to ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," using the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". In this case, each collector pod will hold 2 containers: collector and remover.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/b0fc3de5.3454cfc2.js b/docs/assets/js/b0fc3de5.3454cfc2.js deleted file mode 100644 index a8294b9844..0000000000 --- a/docs/assets/js/b0fc3de5.3454cfc2.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2005],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(r),d=o,f=u["".concat(c,".").concat(d)]||u[d]||m[d]||a;return r?n.createElement(f,i(i({ref:t},p),{},{components:r})):n.createElement(f,i({ref:t},p))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s<a;s++)i[s]=r[s];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},6601:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={title:"Metrics"},i=void 0,l={unversionedId:"metrics",id:"version-v1.0.x/metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.0.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/v1.0.x/metrics",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v1.0.x/customization"},next:{title:"Setup",permalink:"/eraser/docs/v1.0.x/setup"}},c={},s=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}],p={toc:s};function m(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml"},"otelcollector.yaml"),", and the endpoint can be specified using the ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options"},"configmap"),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured."),(0,o.kt)("p",null,"Below is the list of metrics provided by Eraser per run:"),(0,o.kt)("h4",{id:"eraser"},"Eraser"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: images_removed_run_total\n - description: Total images removed by eraser\n")),(0,o.kt)("h4",{id:"scanner"},"Scanner"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: vulnerable_images_run_total\n - description: Total vulnerable images detected\n")),(0,o.kt)("h4",{id:"imagejob"},"ImageJob"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: imagejob_run_total\n - description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n - description: Total pods completed\n - name: pods_failed_run_total\n - description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n - description: Total time for ImageJobs scheduled to complete\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/b0fc3de5.be5ce799.js b/docs/assets/js/b0fc3de5.be5ce799.js new file mode 100644 index 0000000000..dc0c8e6ca0 --- /dev/null +++ b/docs/assets/js/b0fc3de5.be5ce799.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2005],{8705:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(5893),o=n(1151);const a={title:"Metrics"},s=void 0,i={id:"metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.0.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/v1.0.x/metrics",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v1.0.x/customization"},next:{title:"Setup",permalink:"/eraser/docs/v1.0.x/setup"}},c={},l=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}];function d(e){const t={a:"a",code:"code",h4:"h4",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,r.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml",children:"otelcollector.yaml"}),", and the endpoint can be specified using the ",(0,r.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options",children:"configmap"}),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at '",(0,r.jsx)(t.a,{href:"http://localhost:8889/metrics",children:"http://localhost:8889/metrics"}),"', but a separate exporter can also be configured."]}),"\n",(0,r.jsx)(t.p,{children:"Below is the list of metrics provided by Eraser per run:"}),"\n",(0,r.jsx)(t.h4,{id:"eraser",children:"Eraser"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n\t- name: images_removed_run_total\n\t\t- description: Total images removed by eraser\n"})}),"\n",(0,r.jsx)(t.h4,{id:"scanner",children:"Scanner"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: vulnerable_images_run_total\n \t- description: Total vulnerable images detected\n"})}),"\n",(0,r.jsx)(t.h4,{id:"imagejob",children:"ImageJob"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: imagejob_run_total\n \t- description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n \t- description: Total pods completed\n - name: pods_failed_run_total\n \t- description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n \t- description: Total time for ImageJobs scheduled to complete\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>i,a:()=>s});var r=n(7294);const o={},a=r.createContext(o);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b70ea2cb.1f9cdb37.js b/docs/assets/js/b70ea2cb.1f9cdb37.js new file mode 100644 index 0000000000..55f4db0f1b --- /dev/null +++ b/docs/assets/js/b70ea2cb.1f9cdb37.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2534],{4076:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>o,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=n(5893),t=n(1151);const i={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.1.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v1.1.x/releasing",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v1.1.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v1.1.x/custom-scanner"}},o={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2}];function d(e){const r={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.h2,{id:"create-release-pull-request",children:"Create Release Pull Request"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{children:["Go to ",(0,s.jsx)(r.code,{children:"create_release_pull_request"})," workflow under actions."]}),"\n",(0,s.jsx)(r.li,{children:"Select run workflow, and use the workflow from your branch."}),"\n",(0,s.jsx)(r.li,{children:"Input release version with the semantic version identifying the release."}),"\n",(0,s.jsx)(r.li,{children:"Click run workflow and review the PR created by github-actions."}),"\n"]}),"\n",(0,s.jsx)(r.h1,{id:"releasing",children:"Releasing"}),"\n",(0,s.jsxs)(r.ol,{start:"5",children:["\n",(0,s.jsxs)(r.li,{children:["\n",(0,s.jsxs)(r.p,{children:["Once the PR is merged to ",(0,s.jsx)(r.code,{children:"main"}),", tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(r.li,{children:["\n",(0,s.jsxs)(r.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(r.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/remover"}),", ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser-manager"}),", ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/collector"}),", and ",(0,s.jsx)(r.code,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(r.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(r.ol,{children:["\n",(0,s.jsxs)(r.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(r.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]})]})}function h(e={}){const{wrapper:r}={...(0,t.a)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,r,n)=>{n.d(r,{Z:()=>a,a:()=>l});var s=n(7294);const t={},i=s.createContext(t);function l(e){const r=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),s.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b70ea2cb.99ee2f04.js b/docs/assets/js/b70ea2cb.99ee2f04.js deleted file mode 100644 index 11daf5678c..0000000000 --- a/docs/assets/js/b70ea2cb.99ee2f04.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2534],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(r),d=a,g=m["".concat(s,".").concat(d)]||m[d]||u[d]||i;return r?n.createElement(g,l(l({ref:t},p),{},{components:r})):n.createElement(g,l({ref:t},p))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c<i;c++)l[c]=r[c];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},4446:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"version-v1.1.x/releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.1.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/v1.1.x/releasing",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/v1.1.x/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/v1.1.x/custom-scanner"}},s={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"create-release-pull-request"},"Create Release Pull Request"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Go to ",(0,a.kt)("inlineCode",{parentName:"li"},"create_release_pull_request")," workflow under actions."),(0,a.kt)("li",{parentName:"ol"},"Select run workflow, and use the workflow from your branch. "),(0,a.kt)("li",{parentName:"ol"},"Input release version with the semantic version identifying the release."),(0,a.kt)("li",{parentName:"ol"},"Click run workflow and review the PR created by github-actions.")),(0,a.kt)("h1",{id:"releasing"},"Releasing"),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main"),", tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/remover"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/collector"),", and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-trivy-scanner")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/b7730d0d.1c52ffde.js b/docs/assets/js/b7730d0d.1c52ffde.js deleted file mode 100644 index bb61660c9e..0000000000 --- a/docs/assets/js/b7730d0d.1c52ffde.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8976],{3905:(e,r,t)=>{t.d(r,{Zo:()=>l,kt:()=>f});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?i(Object(t),!0).forEach((function(r){o(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function c(e,r){if(null==e)return{};var t,n,o=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},l=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},v=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),v=p(t),f=o,y=v["".concat(s,".").concat(f)]||v[f]||u[f]||i;return t?n.createElement(y,a(a({ref:r},l),{},{components:t})):n.createElement(y,a({ref:r},l))}));function f(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=v;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p<i;p++)a[p]=t[p];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}v.displayName="MDXCreateElement"},1874:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i={title:"Trivy"},a=void 0,c={unversionedId:"trivy",id:"version-v1.2.x/trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.2.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v1.2.x/trivy",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v1.2.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v1.2.x/faq"}},s={},p=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],l={toc:p};function u(e){let{components:r,...t}=e;return(0,o.kt)("wrapper",(0,n.Z)({},l,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,o.kt)("p",null,"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"Customization")," for more details on configuring the scanner."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/b7730d0d.88998729.js b/docs/assets/js/b7730d0d.88998729.js new file mode 100644 index 0000000000..8f2e2b1a56 --- /dev/null +++ b/docs/assets/js/b7730d0d.88998729.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8976],{3453:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var n=r(5893),i=r(1151);const o={title:"Trivy"},s=void 0,a={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.2.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v1.2.x/trivy",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v1.2.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v1.2.x/faq"}},c={},d=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function v(e){const t={a:"a",h2:"h2",p:"p",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,n.jsxs)(t.p,{children:["The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,n.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"Customization"})," for more details on configuring the scanner."]})]})}function u(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(v,{...e})}):v(e)}},1151:(e,t,r)=>{r.d(t,{Z:()=>a,a:()=>s});var n=r(7294);const i={},o=n.createContext(i);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b7cd4035.0ab6a66d.js b/docs/assets/js/b7cd4035.0ab6a66d.js deleted file mode 100644 index 24140f3d46..0000000000 --- a/docs/assets/js/b7cd4035.0ab6a66d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2229],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>g});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(r),g=a,d=m["".concat(s,".").concat(g)]||m[g]||u[g]||i;return r?n.createElement(d,l(l({ref:t},p),{},{components:r})):n.createElement(d,l({ref:t},p))}));function g(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,l=new Array(i);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o.mdxType="string"==typeof e?e:a,l[1]=o;for(var c=2;c<i;c++)l[c]=r[c];return n.createElement.apply(null,l)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},2014:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>i,metadata:()=>o,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"Releasing"},l=void 0,o={unversionedId:"releasing",id:"version-v1.3.x/releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.3.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/releasing",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/custom-scanner"}},s={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2},{value:"Notifying",id:"notifying",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"create-release-pull-request"},"Create Release Pull Request"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Go to ",(0,a.kt)("inlineCode",{parentName:"li"},"create_release_pull_request")," workflow under actions."),(0,a.kt)("li",{parentName:"ol"},"Select run workflow, and use the workflow from your branch. "),(0,a.kt)("li",{parentName:"ol"},"Input release version with the semantic version identifying the release."),(0,a.kt)("li",{parentName:"ol"},"Click run workflow and review the PR created by github-actions.")),(0,a.kt)("h1",{id:"releasing"},"Releasing"),(0,a.kt)("ol",{start:5},(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Once the PR is merged to ",(0,a.kt)("inlineCode",{parentName:"p"},"main"),", tag that commit with release version and push tags to remote repository."),(0,a.kt)("pre",{parentName:"li"},(0,a.kt)("code",{parentName:"pre"},"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"))),(0,a.kt)("li",{parentName:"ol"},(0,a.kt)("p",{parentName:"li"},"Pushing the release tag will trigger GitHub Actions to trigger ",(0,a.kt)("inlineCode",{parentName:"p"},"release")," job.\nThis will build the ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/remover"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-manager"),", ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/collector"),", and ",(0,a.kt)("inlineCode",{parentName:"p"},"ghcr.io/eraser-dev/eraser-trivy-scanner")," images automatically, then publish the new release tag."))),(0,a.kt)("h2",{id:"publishing"},"Publishing"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"GitHub Action will create a new release, review and edit it at ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/eraser-dev/eraser/releases"},"https://github.com/eraser-dev/eraser/releases"))),(0,a.kt)("h2",{id:"notifying"},"Notifying"),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Send an email to the ",(0,a.kt)("a",{parentName:"li",href:"https://groups.google.com/g/eraser-dev"},"Eraser mailing list")," announcing the release, with links to GitHub."),(0,a.kt)("li",{parentName:"ol"},"Post a message on the ",(0,a.kt)("a",{parentName:"li",href:"https://kubernetes.slack.com/archives/C03Q8KV8YQ4"},"Eraser Slack channel")," with the same information.")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/b7cd4035.d3c04a53.js b/docs/assets/js/b7cd4035.d3c04a53.js new file mode 100644 index 0000000000..33696ae402 --- /dev/null +++ b/docs/assets/js/b7cd4035.d3c04a53.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2229],{3496:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>d,frontMatter:()=>t,metadata:()=>a,toc:()=>c});var s=r(5893),i=r(1151);const t={title:"Releasing"},l=void 0,a={id:"releasing",title:"Releasing",description:"Create Release Pull Request",source:"@site/versioned_docs/version-v1.3.x/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/eraser/docs/releasing",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Releasing"},sidebar:"sidebar",previous:{title:"Setup",permalink:"/eraser/docs/setup"},next:{title:"Custom Scanner",permalink:"/eraser/docs/custom-scanner"}},o={},c=[{value:"Create Release Pull Request",id:"create-release-pull-request",level:2},{value:"Publishing",id:"publishing",level:2},{value:"Notifying",id:"notifying",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"create-release-pull-request",children:"Create Release Pull Request"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Go to ",(0,s.jsx)(n.code,{children:"create_release_pull_request"})," workflow under actions."]}),"\n",(0,s.jsx)(n.li,{children:"Select run workflow, and use the workflow from your branch."}),"\n",(0,s.jsx)(n.li,{children:"Input release version with the semantic version identifying the release."}),"\n",(0,s.jsx)(n.li,{children:"Click run workflow and review the PR created by github-actions."}),"\n"]}),"\n",(0,s.jsx)(n.h1,{id:"releasing",children:"Releasing"}),"\n",(0,s.jsxs)(n.ol,{start:"5",children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Once the PR is merged to ",(0,s.jsx)(n.code,{children:"main"}),", tag that commit with release version and push tags to remote repository."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"git checkout <BRANCH NAME>\ngit pull origin <BRANCH NAME>\ngit tag -a <NEW VERSION> -m '<NEW VERSION>'\ngit push origin <NEW VERSION>\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Pushing the release tag will trigger GitHub Actions to trigger ",(0,s.jsx)(n.code,{children:"release"})," job.\nThis will build the ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/remover"}),", ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser-manager"}),", ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/collector"}),", and ",(0,s.jsx)(n.code,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})," images automatically, then publish the new release tag."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"publishing",children:"Publishing"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["GitHub Action will create a new release, review and edit it at ",(0,s.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser/releases",children:"https://github.com/eraser-dev/eraser/releases"})]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"notifying",children:"Notifying"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Send an email to the ",(0,s.jsx)(n.a,{href:"https://groups.google.com/g/eraser-dev",children:"Eraser mailing list"})," announcing the release, with links to GitHub."]}),"\n",(0,s.jsxs)(n.li,{children:["Post a message on the ",(0,s.jsx)(n.a,{href:"https://kubernetes.slack.com/archives/C03Q8KV8YQ4",children:"Eraser Slack channel"})," with the same information."]}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>l});var s=r(7294);const i={},t=s.createContext(i);function l(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b9421f89.292245b3.js b/docs/assets/js/b9421f89.292245b3.js new file mode 100644 index 0000000000..930a2c6361 --- /dev/null +++ b/docs/assets/js/b9421f89.292245b3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7114],{759:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>d,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var i=t(5893),r=t(1151);const s={title:"FAQ"},a=void 0,l={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v0.4.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v0.4.x/faq",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v0.4.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v0.4.x/contributing"}},o={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2}];function u(e){const n={code:"code",h2:"h2",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the ",(0,i.jsx)(n.code,{children:"--severity"})," flag."]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>l,a:()=>a});var i=t(7294);const r={},s=i.createContext(r);function a(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b9421f89.bce75c8a.js b/docs/assets/js/b9421f89.bce75c8a.js deleted file mode 100644 index 7dd562f03f..0000000000 --- a/docs/assets/js/b9421f89.bce75c8a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7114],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(r),f=i,v=m["".concat(s,".").concat(f)]||m[f]||p[f]||a;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var c=2;c<a;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},550:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const a={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"version-v0.4.x/faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v0.4.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v0.4.x/faq",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v0.4.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v0.4.x/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,i.kt)("p",null,"Eraser currently targets ",(0,i.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the ",(0,i.kt)("inlineCode",{parentName:"p"},"--severity")," flag."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bacc1ae0.816015a9.js b/docs/assets/js/bacc1ae0.816015a9.js deleted file mode 100644 index b3df9b47d4..0000000000 --- a/docs/assets/js/bacc1ae0.816015a9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2579],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(r),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=r[l];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}d.displayName="MDXCreateElement"},9955:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"version-v1.3.x/contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.3.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/contributing",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bacc1ae0.c11996b0.js b/docs/assets/js/bacc1ae0.c11996b0.js new file mode 100644 index 0000000000..e26a0deffd --- /dev/null +++ b/docs/assets/js/bacc1ae0.c11996b0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2579],{8282:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.3.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/contributing",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bbedbacb.734bd7d6.js b/docs/assets/js/bbedbacb.734bd7d6.js new file mode 100644 index 0000000000..0b6273e133 --- /dev/null +++ b/docs/assets/js/bbedbacb.734bd7d6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3523],{8819:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,o={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.2.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v1.2.x/architecture",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v1.2.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v1.2.x/manual-removal"}},l={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>o,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bbedbacb.9fcac33b.js b/docs/assets/js/bbedbacb.9fcac33b.js deleted file mode 100644 index b51e962ecd..0000000000 --- a/docs/assets/js/bbedbacb.9fcac33b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3523],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,v=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var s=2;s<i;s++)o[s]=r[s];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},9276:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"version-v1.2.x/architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.2.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v1.2.x/architecture",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v1.2.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v1.2.x/manual-removal"}},c={},s=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],u={toc:s};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bc344202.0b3ac2c6.js b/docs/assets/js/bc344202.0b3ac2c6.js new file mode 100644 index 0000000000..a4ae19f3d1 --- /dev/null +++ b/docs/assets/js/bc344202.0b3ac2c6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6534],{4053:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,o={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.3.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/architecture",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/manual-removal"}},l={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>o,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bc344202.a00f1fb9.js b/docs/assets/js/bc344202.a00f1fb9.js deleted file mode 100644 index 81857dc5d5..0000000000 --- a/docs/assets/js/bc344202.a00f1fb9.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6534],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,f=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(f,o(o({ref:t},u),{},{components:r})):n.createElement(f,o({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var s=2;s<i;s++)o[s]=r[s];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},6279:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"version-v1.3.x/architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.3.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/architecture",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/manual-removal"}},c={},s=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],u={toc:s};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bc8dcae3.4c7ec3a0.js b/docs/assets/js/bc8dcae3.4c7ec3a0.js deleted file mode 100644 index c531a06623..0000000000 --- a/docs/assets/js/bc8dcae3.4c7ec3a0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4815],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?l(Object(r),!0).forEach((function(n){a(e,n,r[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))}))}return e}function s(e,n){if(null==e)return{};var r,t,a=function(e,n){if(null==e)return{};var r,t,a={},l=Object.keys(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c<l;c++)o[c]=r[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,r)}u.displayName="MDXCreateElement"},2289:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"version-v1.3.x/manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.3.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/manual-removal",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n')),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," is a cluster-scoped resource and must be called imagelist. ",(0,a.kt)("inlineCode",{parentName:"p"},'"*"')," can be specified to remove all non-running images instead of individual images.")),(0,a.kt)("p",null,"Creating an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," should trigger an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageJob")," that will deploy Eraser pods on every node to perform the removal given the list of images."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n")),(0,a.kt)("p",null,"Pods will run to completion and the images will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n")),(0,a.kt)("p",null,"Verify the unused images are removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n")),(0,a.kt)("p",null,"If the image has been successfully removed, there will be no output."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bc8dcae3.deeb5da5.js b/docs/assets/js/bc8dcae3.deeb5da5.js new file mode 100644 index 0000000000..28d93de274 --- /dev/null +++ b/docs/assets/js/bc8dcae3.deeb5da5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4815],{6208:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.3.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/manual-removal",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"ImageList"})," is a cluster-scoped resource and must be called imagelist. ",(0,r.jsx)(n.code,{children:'"*"'})," can be specified to remove all non-running images instead of individual images."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Creating an ",(0,r.jsx)(n.code,{children:"ImageList"})," should trigger an ",(0,r.jsx)(n.code,{children:"ImageJob"})," that will deploy Eraser pods on every node to perform the removal given the list of images."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n"})}),"\n",(0,r.jsx)(n.p,{children:"Pods will run to completion and the images will be removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"ImageList"})," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"Verify the unused images are removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n"})}),"\n",(0,r.jsx)(n.p,{children:"If the image has been successfully removed, there will be no output."})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bdb5eb86.9d21e19a.js b/docs/assets/js/bdb5eb86.9d21e19a.js new file mode 100644 index 0000000000..77e48ac8dd --- /dev/null +++ b/docs/assets/js/bdb5eb86.9d21e19a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8411],{8083:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>o,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,o={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.0.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v1.0.x/architecture",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v1.0.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v1.0.x/manual-removal"}},l={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>o,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function o(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bdb5eb86.b95ff3d4.js b/docs/assets/js/bdb5eb86.b95ff3d4.js deleted file mode 100644 index d89e4ba57f..0000000000 --- a/docs/assets/js/bdb5eb86.b95ff3d4.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8411],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,v=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var s=2;s<i;s++)o[s]=r[s];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},3591:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"version-v1.0.x/architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v1.0.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v1.0.x/architecture",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v1.0.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v1.0.x/manual-removal"}},c={},s=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],u={toc:s};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bf5c5542.4f1330ce.js b/docs/assets/js/bf5c5542.4f1330ce.js deleted file mode 100644 index c84d72b303..0000000000 --- a/docs/assets/js/bf5c5542.4f1330ce.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[548],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},v=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),v=c(r),f=i,d=v["".concat(s,".").concat(f)]||v[f]||u[f]||o;return r?n.createElement(d,a(a({ref:t},p),{},{components:r})):n.createElement(d,a({ref:t},p))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=r.length,a=new Array(o);a[0]=v;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,a[1]=l;for(var c=2;c<o;c++)a[c]=r[c];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}v.displayName="MDXCreateElement"},2241:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const o={title:"Trivy"},a=void 0,l={unversionedId:"trivy",id:"version-v0.5.x/trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v0.5.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v0.5.x/trivy",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v0.5.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v0.5.x/faq"}},s={},c=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,i.kt)("p",null,"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"--ignore-unfixed: boolean to report only fixed vulnerabilities (default true)"),(0,i.kt)("li",{parentName:"ul"},'--security-checks: comma-separated list of what security issues to detect (default "vuln")'),(0,i.kt)("li",{parentName:"ul"},'--vuln-type: list of severity levels to report (default "CRITICAL")'),(0,i.kt)("li",{parentName:"ul"},"--delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/bf5c5542.ec01ec49.js b/docs/assets/js/bf5c5542.ec01ec49.js new file mode 100644 index 0000000000..b087d2cef2 --- /dev/null +++ b/docs/assets/js/bf5c5542.ec01ec49.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[548],{5079:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var i=n(5893),r=n(1151);const s={title:"Trivy"},o=void 0,l={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v0.5.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v0.5.x/trivy",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v0.5.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v0.5.x/faq"}},a={},c=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function d(e){const t={h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,i.jsx)(t.p,{children:"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"--ignore-unfixed: boolean to report only fixed vulnerabilities (default true)"}),"\n",(0,i.jsx)(t.li,{children:'--security-checks: comma-separated list of what security issues to detect (default "vuln")'}),"\n",(0,i.jsx)(t.li,{children:'--vuln-type: list of severity levels to report (default "CRITICAL")'}),"\n",(0,i.jsx)(t.li,{children:"--delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)"}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>l,a:()=>o});var i=n(7294);const r={},s=i.createContext(r);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bffae3e7.d211ec7b.js b/docs/assets/js/bffae3e7.d211ec7b.js new file mode 100644 index 0000000000..131ec4ef8a --- /dev/null +++ b/docs/assets/js/bffae3e7.d211ec7b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7092],{4726:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var s=n(5893),o=n(1151);const i={title:"Contributing"},r=void 0,c={id:"contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.1.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v1.1.x/contributing",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v1.1.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v1.1.x/code-of-conduct"}},a={},d=[];function l(e){const t={a:"a",code:"code",li:"li",p:"p",ul:"ul",...(0,o.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"There are several ways to get involved with Eraser"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.a,{href:"https://groups.google.com/u/1/g/eraser-dev",children:"mailing list"})," to get notifications for releases, security announcements, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Participate in the ",(0,s.jsx)(t.a,{href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit",children:"biweekly community meetings"})," to disucss development, issues, use cases, etc."]}),"\n",(0,s.jsxs)(t.li,{children:["Join the ",(0,s.jsx)(t.code,{children:"#eraser"})," channel on the ",(0,s.jsx)(t.a,{href:"https://slack.k8s.io/",children:"Kubernetes Slack"})]}),"\n",(0,s.jsxs)(t.li,{children:["View the ",(0,s.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/development",children:"development setup instructions"})]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This project welcomes contributions and suggestions."}),"\n",(0,s.jsxs)(t.p,{children:["This project has adopted the ",(0,s.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]})]})}function u(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>c,a:()=>r});var s=n(7294);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bffae3e7.d34bc0df.js b/docs/assets/js/bffae3e7.d34bc0df.js deleted file mode 100644 index 30e012064a..0000000000 --- a/docs/assets/js/bffae3e7.d34bc0df.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7092],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function c(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),l=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),d=l(r),m=o,f=d["".concat(s,".").concat(m)]||d[m]||p[m]||i;return r?n.createElement(f,a(a({ref:t},u),{},{components:r})):n.createElement(f,a({ref:t},u))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=d;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var l=2;l<i;l++)a[l]=r[l];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}d.displayName="MDXCreateElement"},3707:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const i={title:"Contributing"},a=void 0,c={unversionedId:"contributing",id:"version-v1.1.x/contributing",title:"Contributing",description:"There are several ways to get involved with Eraser",source:"@site/versioned_docs/version-v1.1.x/contributing.md",sourceDirName:".",slug:"/contributing",permalink:"/eraser/docs/v1.1.x/contributing",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Contributing"},sidebar:"sidebar",previous:{title:"FAQ",permalink:"/eraser/docs/v1.1.x/faq"},next:{title:"Code of Conduct",permalink:"/eraser/docs/v1.1.x/code-of-conduct"}},s={},l=[],u={toc:l};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"There are several ways to get involved with Eraser"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("a",{parentName:"li",href:"https://groups.google.com/u/1/g/eraser-dev"},"mailing list")," to get notifications for releases, security announcements, etc."),(0,o.kt)("li",{parentName:"ul"},"Participate in the ",(0,o.kt)("a",{parentName:"li",href:"https://docs.google.com/document/d/1Sj5u47K3WUGYNPmQHGFpb52auqZb1FxSlWAQnPADhWI/edit"},"biweekly community meetings")," to disucss development, issues, use cases, etc."),(0,o.kt)("li",{parentName:"ul"},"Join the ",(0,o.kt)("inlineCode",{parentName:"li"},"#eraser")," channel on the ",(0,o.kt)("a",{parentName:"li",href:"https://slack.k8s.io/"},"Kubernetes Slack")),(0,o.kt)("li",{parentName:"ul"},"View the ",(0,o.kt)("a",{parentName:"li",href:"https://eraser-dev.github.io/eraser/docs/development"},"development setup instructions"))),(0,o.kt)("p",null,"This project welcomes contributions and suggestions."),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c108e81c.3dfa39c8.js b/docs/assets/js/c108e81c.3dfa39c8.js new file mode 100644 index 0000000000..57ea3935f4 --- /dev/null +++ b/docs/assets/js/c108e81c.3dfa39c8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2156],{3817:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v0.4.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v0.4.x/manual-removal",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v0.4.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v0.4.x/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"ImageList"})," is a cluster-scoped resource and must be called imagelist. ",(0,r.jsx)(n.code,{children:'"*"'})," can be specified to remove all non-running images instead of individual images."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Creating an ",(0,r.jsx)(n.code,{children:"ImageList"})," should trigger an ",(0,r.jsx)(n.code,{children:"ImageJob"})," that will deploy Eraser pods on every node to perform the removal given the list of images."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n"})}),"\n",(0,r.jsx)(n.p,{children:"Pods will run to completion and the images will be removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"ImageList"})," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"Verify the unused images are removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n"})}),"\n",(0,r.jsx)(n.p,{children:"If the image has been successfully removed, there will be no output."})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/c108e81c.619f3030.js b/docs/assets/js/c108e81c.619f3030.js deleted file mode 100644 index d7d14fc15b..0000000000 --- a/docs/assets/js/c108e81c.619f3030.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2156],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?l(Object(r),!0).forEach((function(n){a(e,n,r[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))}))}return e}function s(e,n){if(null==e)return{};var r,t,a=function(e,n){if(null==e)return{};var r,t,a={},l=Object.keys(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c<l;c++)o[c]=r[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,r)}u.displayName="MDXCreateElement"},2852:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"version-v0.4.x/manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v0.4.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v0.4.x/manual-removal",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v0.4.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v0.4.x/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n')),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," is a cluster-scoped resource and must be called imagelist. ",(0,a.kt)("inlineCode",{parentName:"p"},'"*"')," can be specified to remove all non-running images instead of individual images.")),(0,a.kt)("p",null,"Creating an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," should trigger an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageJob")," that will deploy Eraser pods on every node to perform the removal given the list of images."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n")),(0,a.kt)("p",null,"Pods will run to completion and the images will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n")),(0,a.kt)("p",null,"Verify the unused images are removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n")),(0,a.kt)("p",null,"If the image has been successfully removed, there will be no output."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c12dc9fd.1b6a252d.js b/docs/assets/js/c12dc9fd.1b6a252d.js deleted file mode 100644 index 963b59443b..0000000000 --- a/docs/assets/js/c12dc9fd.1b6a252d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6325],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l<c;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},4606:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"version-v0.4.x/code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v0.4.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v0.4.x/code-of-conduct",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v0.4.x/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c12dc9fd.ade4b346.js b/docs/assets/js/c12dc9fd.ade4b346.js new file mode 100644 index 0000000000..9ef1a1cc4a --- /dev/null +++ b/docs/assets/js/c12dc9fd.ade4b346.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6325],{1294:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>f,frontMatter:()=>d,metadata:()=>i,toc:()=>u});var n=t(5893),c=t(1151);const d={title:"Code of Conduct"},s=void 0,i={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v0.4.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v0.4.x/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v0.4.x/contributing"}},r={},u=[];function a(e){const o={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["This project has adopted the ",(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"Resources:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:o}={...(0,c.a)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,o,t)=>{t.d(o,{Z:()=>i,a:()=>s});var n=t(7294);const c={},d=n.createContext(c);function s(e){const o=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(d.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/c4f50fcb.b3a1918d.js b/docs/assets/js/c4f50fcb.b3a1918d.js deleted file mode 100644 index af0be98467..0000000000 --- a/docs/assets/js/c4f50fcb.b3a1918d.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[907],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(c,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},7644:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",s={unversionedId:"introduction",id:"version-v1.2.x/introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.2.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v1.2.x/",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v1.2.x/installation"}},c={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c4f50fcb.ddfb9faa.js b/docs/assets/js/c4f50fcb.ddfb9faa.js new file mode 100644 index 0000000000..6d97cc67ec --- /dev/null +++ b/docs/assets/js/c4f50fcb.ddfb9faa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[907],{5911:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.2.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v1.2.x/",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v1.2.x/installation"}},c={},d=[];function l(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/c66bbf8a.13446857.js b/docs/assets/js/c66bbf8a.13446857.js new file mode 100644 index 0000000000..bccccc2973 --- /dev/null +++ b/docs/assets/js/c66bbf8a.13446857.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[568],{4800:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v0.5.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v0.5.x/",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v0.5.x/installation"}},c={},d=[];function l(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/c66bbf8a.1acc839f.js b/docs/assets/js/c66bbf8a.1acc839f.js deleted file mode 100644 index f7c5b75a99..0000000000 --- a/docs/assets/js/c66bbf8a.1acc839f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[568],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(c,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},789:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",s={unversionedId:"introduction",id:"version-v0.5.x/introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v0.5.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v0.5.x/",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v0.5.x/installation"}},c={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c698fe77.164c142f.js b/docs/assets/js/c698fe77.164c142f.js deleted file mode 100644 index 664bcf165c..0000000000 --- a/docs/assets/js/c698fe77.164c142f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4993],{6283:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v0.4.x","label":"v0.4.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v0.4.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v0.4.x/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/v0.4.x/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/v0.4.x/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/v0.4.x/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v0.4.x/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/v0.4.x/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/v0.4.x/customization","docId":"customization"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v0.4.x/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/v0.4.x/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v0.4.x/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/v0.4.x/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v0.4.x/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/v0.4.x/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v0.4.x/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Overview","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/c698fe77.a9373167.js b/docs/assets/js/c698fe77.a9373167.js new file mode 100644 index 0000000000..879cb82852 --- /dev/null +++ b/docs/assets/js/c698fe77.a9373167.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4993],{6283:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v0.4.x","label":"v0.4.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v0.4.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v0.4.x/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/v0.4.x/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/v0.4.x/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/v0.4.x/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v0.4.x/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/v0.4.x/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/v0.4.x/customization","docId":"customization","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v0.4.x/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/v0.4.x/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v0.4.x/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/v0.4.x/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v0.4.x/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/v0.4.x/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v0.4.x/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Overview","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/c73303db.0eee1cb1.js b/docs/assets/js/c73303db.0eee1cb1.js new file mode 100644 index 0000000000..495613629b --- /dev/null +++ b/docs/assets/js/c73303db.0eee1cb1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5082],{7328:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var s=n(5893),r=n(1151);const a={title:"Installation"},i=void 0,o={id:"installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v0.5.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v0.5.x/installation",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v0.5.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v0.5.x/quick-start"}},l={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,r.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h2,{id:"manifest",children:"Manifest"}),"\n",(0,s.jsx)(t.p,{children:"To install Eraser with the manifest file, run the following command:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.5.0/deploy/eraser.yaml\n"})}),"\n",(0,s.jsx)(t.h2,{id:"helm",children:"Helm"}),"\n",(0,s.jsxs)(t.p,{children:["If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,s.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"here"})]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>o,a:()=>i});var s=n(7294);const r={},a=s.createContext(r);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/c73303db.be916204.js b/docs/assets/js/c73303db.be916204.js deleted file mode 100644 index cb6925efb1..0000000000 --- a/docs/assets/js/c73303db.be916204.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5082],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),f=c(r),m=a,d=f["".concat(s,".").concat(m)]||f[m]||u[m]||o;return r?n.createElement(d,i(i({ref:t},p),{},{components:r})):n.createElement(d,i({ref:t},p))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,i=new Array(o);i[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<o;c++)i[c]=r[c];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},2992:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const o={title:"Installation"},i=void 0,l={unversionedId:"installation",id:"version-v0.5.x/installation",title:"Installation",description:"Manifest",source:"@site/versioned_docs/version-v0.5.x/installation.md",sourceDirName:".",slug:"/installation",permalink:"/eraser/docs/v0.5.x/installation",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Installation"},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/eraser/docs/v0.5.x/"},next:{title:"Quick Start",permalink:"/eraser/docs/v0.5.x/quick-start"}},s={},c=[{value:"Manifest",id:"manifest",level:2},{value:"Helm",id:"helm",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"manifest"},"Manifest"),(0,a.kt)("p",null,"To install Eraser with the manifest file, run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.5.0/deploy/eraser.yaml\n")),(0,a.kt)("h2",{id:"helm"},"Helm"),(0,a.kt)("p",null,"If you'd like to install and manage Eraser with Helm, follow the install instructions ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"here")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c853dc39.2fc0de50.js b/docs/assets/js/c853dc39.2fc0de50.js deleted file mode 100644 index 7884ca4e51..0000000000 --- a/docs/assets/js/c853dc39.2fc0de50.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7028],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>s});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?l(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):l(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)n=l[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=a.createContext({}),m=function(e){var t=a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=m(e.components);return a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},k=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,l=e.originalType,p=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),k=m(n),s=r,g=k["".concat(p,".").concat(s)]||k[s]||d[s]||l;return n?a.createElement(g,i(i({ref:t},u),{},{components:n})):a.createElement(g,i({ref:t},u))}));function s(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var l=n.length,i=new Array(l);i[0]=k;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var m=2;m<l;m++)i[m]=n[m];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}k.displayName="MDXCreateElement"},2001:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const l={title:"Setup"},i="Development Setup",o={unversionedId:"setup",id:"version-v1.3.x/setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.3.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/setup",draft:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/releasing"}},p={},m=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}],u={toc:m};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"development-setup"},"Development Setup"),(0,r.kt)("p",null,"This document describes the steps to get started with development.\nYou can either utilize ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/codespaces/overview"},"Codespaces")," or setup a local environment."),(0,r.kt)("h2",{id:"local-setup"},"Local Setup"),(0,r.kt)("h3",{id:"prerequisites"},"Prerequisites:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://go.dev/"},"go")," with version 1.17 or later."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://docs.docker.com/get-docker/"},"docker")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"https://kind.sigs.k8s.io/"},"kind")),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make"))),(0,r.kt)("h3",{id:"get-things-running"},"Get things running"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"Get dependencies with ",(0,r.kt)("inlineCode",{parentName:"p"},"go get"))),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("p",{parentName:"li"},"This project uses ",(0,r.kt)("inlineCode",{parentName:"p"},"make"),". You can utilize ",(0,r.kt)("inlineCode",{parentName:"p"},"make help")," to see available targets. For local deployment make targets help to build, test and deploy."))),(0,r.kt)("h3",{id:"making-changes"},"Making changes"),(0,r.kt)("p",null,"Please refer to ",(0,r.kt)("a",{parentName:"p",href:"#development-reference"},"Development Reference")," for more details on the specific commands."),(0,r.kt)("p",null,"To test your changes on a cluster:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n")),(0,r.kt)("p",null,"To test your changes to manager locally:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"make run\n")),(0,r.kt)("p",null,"Example Output:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n')),(0,r.kt)("h2",{id:"development-reference"},"Development Reference"),(0,r.kt)("p",null,"Eraser is using tooling from ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/kubernetes-sigs/kubebuilder"},"kubebuilder"),". For Eraser this tooling is containerized into the ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-tooling")," image. The ",(0,r.kt)("inlineCode",{parentName:"p"},"make")," targets can use this tooling and build the image when necessary."),(0,r.kt)("p",null,"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."),(0,r.kt)("h3",{id:"common-configuration"},"Common Configuration"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the version (i.e., the image tag) of eraser to be used.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Collector. Used for tagging, pulling and pushing the image")))),(0,r.kt)("h3",{id:"linting"},"Linting"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make lint"))),(0,r.kt)("p",null,"Lints the go code."),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"GOLANGCI_LINT"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the go linting binary to be used for linting.")))),(0,r.kt)("h3",{id:"development"},"Development"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make generate"))),(0,r.kt)("p",null,"Generates necessary files for the k8s api stored under ",(0,r.kt)("inlineCode",{parentName:"p"},"api/v1alpha1/zz_generated.deepcopy.go"),". See the ",(0,r.kt)("a",{parentName:"p",href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html"},"kubebuilder docs")," for details."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make manifests"))),(0,r.kt)("p",null,"Generates the eraser deployment yaml files under ",(0,r.kt)("inlineCode",{parentName:"p"},"manifest_staging/deploy"),"."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Defines the image url for the Eraser manager.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Define Kustomize version for generating manifests.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make test"))),(0,r.kt)("p",null,"Runs the unit tests for the eraser project."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the envtest setup binary.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"ENVTEST_K8S_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the Kubernetes version for envtest setup command.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make e2e-test"))),(0,r.kt)("p",null,"Runs e2e tests on a cluster."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Eraser manager image to be used for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUBERNETES_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kubernetes version for e2e test.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TEST_COUNT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets repetition for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TIMEOUT"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets timeout for test. Please refer to ",(0,r.kt)("a",{parentName:"td",href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags"},"go docs")," for details.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"TESTFLAGS"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets additional test flags")))),(0,r.kt)("h3",{id:"build"},"Build"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make build"))),(0,r.kt)("p",null,"Builds the eraser manager binaries."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make run"))),(0,r.kt)("p",null,"Runs the eraser manager on your local machine."),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-manager"))),(0,r.kt)("p",null,"Builds the docker image for the eraser manager."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-remover"))),(0,r.kt)("p",null,"Builds the docker image for eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-remover"))),(0,r.kt)("p",null,"Builds the docker image for the eraser remover."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"REMOVER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-build-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_FROM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-from flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"CACHE_TO"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target of the buildx --cache-to flag ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"PLATFORM"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the target platform for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"OUTPUT_TYPE"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the output for buildx ",(0,r.kt)("a",{parentName:"td",href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output"},"see buildx reference"),".")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make docker-push-collector"))),(0,r.kt)("p",null,"Builds the docker image for the eraser collector."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"COLLECTOR_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the target repository, image name and tag for building image.")))),(0,r.kt)("h3",{id:"deployment"},"Deployment"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make install"))),(0,r.kt)("p",null,"Install CRDs into the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make uninstall"))),(0,r.kt)("p",null,"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make deploy"))),(0,r.kt)("p",null,"Deploys eraser to the cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources for deployment.")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"MANAGER_IMG"),(0,r.kt)("td",{parentName:"tr",align:null},"Specifies the eraser manager image version to be used for deployment")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make undeploy"))),(0,r.kt)("p",null,"Undeploy controller from the K8s cluster specified in ~/.kube/config."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"KUSTOMIZE_VERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Kustomize version used to generate k8s resources that need to be removed.")))),(0,r.kt)("h3",{id:"release"},"Release"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make release-manifest"))),(0,r.kt)("p",null,"Generates k8s manifests files for a release."),(0,r.kt)("p",null,"Configuration Options:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Environment Variable"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"NEWVERSION"),(0,r.kt)("td",{parentName:"tr",align:null},"Sets the new version in the Makefile")))),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("inlineCode",{parentName:"li"},"make promote-staging-manifest"))),(0,r.kt)("p",null,"Promotes the k8s deployment yaml files to release."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c853dc39.861078cc.js b/docs/assets/js/c853dc39.861078cc.js new file mode 100644 index 0000000000..98bee1cf6c --- /dev/null +++ b/docs/assets/js/c853dc39.861078cc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7028],{9846:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>a,frontMatter:()=>t,metadata:()=>l,toc:()=>h});var i=r(5893),s=r(1151);const t={title:"Setup"},d="Development Setup",l={id:"setup",title:"Setup",description:"This document describes the steps to get started with development.",source:"@site/versioned_docs/version-v1.3.x/setup.md",sourceDirName:".",slug:"/setup",permalink:"/eraser/docs/setup",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{title:"Setup"},sidebar:"sidebar",previous:{title:"Metrics",permalink:"/eraser/docs/metrics"},next:{title:"Releasing",permalink:"/eraser/docs/releasing"}},c={},h=[{value:"Local Setup",id:"local-setup",level:2},{value:"Prerequisites:",id:"prerequisites",level:3},{value:"Get things running",id:"get-things-running",level:3},{value:"Making changes",id:"making-changes",level:3},{value:"Development Reference",id:"development-reference",level:2},{value:"Common Configuration",id:"common-configuration",level:3},{value:"Linting",id:"linting",level:3},{value:"Development",id:"development",level:3},{value:"Build",id:"build",level:3},{value:"Deployment",id:"deployment",level:3},{value:"Release",id:"release",level:3}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,s.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"development-setup",children:"Development Setup"}),"\n",(0,i.jsxs)(n.p,{children:["This document describes the steps to get started with development.\nYou can either utilize ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/codespaces/overview",children:"Codespaces"})," or setup a local environment."]}),"\n",(0,i.jsx)(n.h2,{id:"local-setup",children:"Local Setup"}),"\n",(0,i.jsx)(n.h3,{id:"prerequisites",children:"Prerequisites:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"https://go.dev/",children:"go"})," with version 1.17 or later."]}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://docs.docker.com/get-docker/",children:"docker"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://kind.sigs.k8s.io/",children:"kind"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make"})}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"get-things-running",children:"Get things running"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Get dependencies with ",(0,i.jsx)(n.code,{children:"go get"})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["This project uses ",(0,i.jsx)(n.code,{children:"make"}),". You can utilize ",(0,i.jsx)(n.code,{children:"make help"})," to see available targets. For local deployment make targets help to build, test and deploy."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"making-changes",children:"Making changes"}),"\n",(0,i.jsxs)(n.p,{children:["Please refer to ",(0,i.jsx)(n.a,{href:"#development-reference",children:"Development Reference"})," for more details on the specific commands."]}),"\n",(0,i.jsx)(n.p,{children:"To test your changes on a cluster:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# generate necessary api files (optional - only needed if changes to api folder).\nmake generate\n\n# build applicable images\nmake docker-build-manager MANAGER_IMG=eraser-manager:dev\nmake docker-build-remover REMOVER_IMG=remover:dev\nmake docker-build-collector COLLECTOR_IMG=collector:dev\nmake docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev\n\n# make sure updated image is present on cluster (e.g., see kind example below)\nkind load docker-image \\\n eraser-manager:dev \\\n eraser-trivy-scanner:dev \\\n remover:dev \\\n collector:dev\n\nmake manifests\nmake deploy\n\n# to remove the deployment\nmake undeploy\n"})}),"\n",(0,i.jsx)(n.p,{children:"To test your changes to manager locally:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"make run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Example Output:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'you@local:~/eraser$ make run\ndocker build . \\\n -t eraser-tooling \\\n -f build/tooling/Dockerfile\n[+] Building 7.8s (8/8) FINISHED\n => => naming to docker.io/library/eraser-tooling 0.0s\ndocker run -v /home/eraser/config:/config -w /config/manager \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen \\\n crd \\\n rbac:roleName=manager-role \\\n webhook \\\n paths="./..." \\\n output:crd:artifacts:config=config/crd/bases\nrm -rf manifest_staging\nmkdir -p manifest_staging/deploy\ndocker run --rm -v /home/eraser:/eraser \\\n registry.k8s.io/kustomize/kustomize:v3.8.9 build \\\n /eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml\ndocker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."\ngo fmt ./...\ngo vet ./...\ngo run ./main.go\n{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}\n...\n'})}),"\n",(0,i.jsx)(n.h2,{id:"development-reference",children:"Development Reference"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser is using tooling from ",(0,i.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder",children:"kubebuilder"}),". For Eraser this tooling is containerized into the ",(0,i.jsx)(n.code,{children:"eraser-tooling"})," image. The ",(0,i.jsx)(n.code,{children:"make"})," targets can use this tooling and build the image when necessary."]}),"\n",(0,i.jsx)(n.p,{children:"You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options."}),"\n",(0,i.jsx)(n.h3,{id:"common-configuration",children:"Common Configuration"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the version (i.e., the image tag) of eraser to be used."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser. Used for tagging, pulling and pushing the image"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Collector. Used for tagging, pulling and pushing the image"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"linting",children:"Linting"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make lint"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Lints the go code."}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"GOLANGCI_LINT"}),(0,i.jsx)(n.td,{children:"Specifies the go linting binary to be used for linting."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"development",children:"Development"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make generate"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates necessary files for the k8s api stored under ",(0,i.jsx)(n.code,{children:"api/v1alpha1/zz_generated.deepcopy.go"}),". See the ",(0,i.jsx)(n.a,{href:"https://book.kubebuilder.io/cronjob-tutorial/other-api-files.html",children:"kubebuilder docs"})," for details."]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make manifests"})}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["Generates the eraser deployment yaml files under ",(0,i.jsx)(n.code,{children:"manifest_staging/deploy"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Defines the image url for the Eraser manager."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Define Kustomize version for generating manifests."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the unit tests for the eraser project."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST"}),(0,i.jsx)(n.td,{children:"Specifies the envtest setup binary."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"ENVTEST_K8S_VERSION"}),(0,i.jsx)(n.td,{children:"Specifies the Kubernetes version for envtest setup command."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make e2e-test"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs e2e tests on a cluster."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Eraser manager image to be used for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUBERNETES_VERSION"}),(0,i.jsx)(n.td,{children:"Kubernetes version for e2e test."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TEST_COUNT"}),(0,i.jsxs)(n.td,{children:["Sets repetition for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TIMEOUT"}),(0,i.jsxs)(n.td,{children:["Sets timeout for test. Please refer to ",(0,i.jsx)(n.a,{href:"https://pkg.go.dev/cmd/go#hdr-Testing_flags",children:"go docs"})," for details."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"TESTFLAGS"}),(0,i.jsx)(n.td,{children:"Sets additional test flags"})]})]})]}),"\n",(0,i.jsx)(n.h3,{id:"build",children:"Build"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make build"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the eraser manager binaries."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make run"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Runs the eraser manager on your local machine."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-manager"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser manager."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-remover"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser remover."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"REMOVER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-build-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_FROM"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-from flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"CACHE_TO"}),(0,i.jsxs)(n.td,{children:["Sets the target of the buildx --cache-to flag ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"PLATFORM"}),(0,i.jsxs)(n.td,{children:["Sets the target platform for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#platform",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"OUTPUT_TYPE"}),(0,i.jsxs)(n.td,{children:["Sets the output for buildx ",(0,i.jsx)(n.a,{href:"https://docs.docker.com/engine/reference/commandline/buildx_build/#output",children:"see buildx reference"}),"."]})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make docker-push-collector"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Builds the docker image for the eraser collector."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"COLLECTOR_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the target repository, image name and tag for building image."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"deployment",children:"Deployment"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make install"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Install CRDs into the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make uninstall"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Uninstall CRDs from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make deploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Deploys eraser to the cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources for deployment."})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"MANAGER_IMG"}),(0,i.jsx)(n.td,{children:"Specifies the eraser manager image version to be used for deployment"})]})]})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make undeploy"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Undeploy controller from the K8s cluster specified in ~/.kube/config."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"KUSTOMIZE_VERSION"}),(0,i.jsx)(n.td,{children:"Kustomize version used to generate k8s resources that need to be removed."})]})})]}),"\n",(0,i.jsx)(n.h3,{id:"release",children:"Release"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make release-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Generates k8s manifests files for a release."}),"\n",(0,i.jsx)(n.p,{children:"Configuration Options:"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Environment Variable"}),(0,i.jsx)(n.th,{children:"Description"})]})}),(0,i.jsx)(n.tbody,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:"NEWVERSION"}),(0,i.jsx)(n.td,{children:"Sets the new version in the Makefile"})]})})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.code,{children:"make promote-staging-manifest"})}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Promotes the k8s deployment yaml files to release."})]})}function a(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(o,{...e})}):o(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>l,a:()=>d});var i=r(7294);const s={},t=i.createContext(s);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/c9ca4745.da4f0967.js b/docs/assets/js/c9ca4745.da4f0967.js deleted file mode 100644 index 550c96efe9..0000000000 --- a/docs/assets/js/c9ca4745.da4f0967.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5243],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},u=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),d=l(n),m=o,f=d["".concat(c,".").concat(m)]||d[m]||p[m]||i;return n?r.createElement(f,a(a({ref:t},u),{},{components:n})):r.createElement(f,a({ref:t},u))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=n.length,a=new Array(i);a[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,a[1]=s;for(var l=2;l<i;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},4879:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>s,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const i={title:"Introduction",slug:"/"},a="Introduction",s={unversionedId:"introduction",id:"version-v1.1.x/introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.1.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v1.1.x/",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v1.1.x/installation"}},c={},l=[],u={toc:l};function p(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"introduction"},"Introduction"),(0,o.kt)("p",null,"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."),(0,o.kt)("p",null,"The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.kt)("strong",{parentName:"p"},"Eraser")," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/c9ca4745.e2a7d363.js b/docs/assets/js/c9ca4745.e2a7d363.js new file mode 100644 index 0000000000..133a47562a --- /dev/null +++ b/docs/assets/js/c9ca4745.e2a7d363.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5243],{1379:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var o=n(5893),s=n(1151);const i={title:"Introduction",slug:"/"},r="Introduction",a={id:"introduction",title:"Introduction",description:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.",source:"@site/versioned_docs/version-v1.1.x/introduction.md",sourceDirName:".",slug:"/",permalink:"/eraser/docs/v1.1.x/",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Introduction",slug:"/"},sidebar:"sidebar",next:{title:"Installation",permalink:"/eraser/docs/v1.1.x/installation"}},c={},d=[];function l(e){const t={h1:"h1",p:"p",strong:"strong",...(0,s.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsx)(t.p,{children:"When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes."}),"\n",(0,o.jsxs)(t.p,{children:["The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. ",(0,o.jsx)(t.strong,{children:"Eraser"})," aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria."]})]})}function u(e={}){const{wrapper:t}={...(0,s.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>a,a:()=>r});var o=n(7294);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/d40dbec5.3ea65837.js b/docs/assets/js/d40dbec5.3ea65837.js deleted file mode 100644 index 826f8c78c3..0000000000 --- a/docs/assets/js/d40dbec5.3ea65837.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7677],{3905:(e,r,t)=>{t.d(r,{Zo:()=>c,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?a(Object(t),!0).forEach((function(r){i(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function o(e,r){if(null==e)return{};var t,n,i=function(e,r){if(null==e)return{};var t,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)t=a[n],r.indexOf(t)>=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)t=a[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},c=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},d={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),u=p(t),m=i,f=u["".concat(s,".").concat(m)]||u[m]||d[m]||a;return t?n.createElement(f,l(l({ref:r},c),{},{components:t})):n.createElement(f,l({ref:r},c))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var a=t.length,l=new Array(a);l[0]=u;var o={};for(var s in r)hasOwnProperty.call(r,s)&&(o[s]=r[s]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var p=2;p<a;p++)l[p]=t[p];return n.createElement.apply(null,l)}return n.createElement.apply(null,t)}u.displayName="MDXCreateElement"},2646:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>p});var n=t(7462),i=(t(7294),t(3905));const a={title:"Exclusion"},l=void 0,o={unversionedId:"exclusion",id:"version-v0.4.x/exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v0.4.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v0.4.x/exclusion",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v0.4.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v0.4.x/customization"}},s={},p=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],c={toc:p};function d(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},c,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<EOF\n{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}\nEOF\n\n$ kubectl create configmap excluded --from-file=excluded=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes with ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes")," is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes")," argument. "),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"See ",(0,i.kt)("a",{parentName:"em",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"Eraser Helm Chart")," for more information on deployment.")),(0,i.kt)("p",null,"Nodes with the selector ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter")," will be filtered accordingly. "),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"If ",(0,i.kt)("inlineCode",{parentName:"li"},"include")," is provided, eraser and collector pods will only be scheduled on nodes with the selector ",(0,i.kt)("inlineCode",{parentName:"li"},"eraser.sh/cleanup.filter"),". "),(0,i.kt)("li",{parentName:"ul"},"If ",(0,i.kt)("inlineCode",{parentName:"li"},"exclude")," is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector ",(0,i.kt)("inlineCode",{parentName:"li"},"eraser.sh/cleanup.filter"),".")),(0,i.kt)("p",null,"Unless specified, the default value of ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes")," is ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude"),". Because Windows nodes are not supported, they will always be excluded regardless of the ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter")," label or the value of ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes"),"."),(0,i.kt)("p",null,"Additional node selectors can be provided through the ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes-selector")," flag."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/d40dbec5.8e7bd9d0.js b/docs/assets/js/d40dbec5.8e7bd9d0.js new file mode 100644 index 0000000000..7227671745 --- /dev/null +++ b/docs/assets/js/d40dbec5.8e7bd9d0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[7677],{6026:(e,s,r)=>{r.r(s),r.d(s,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>t,toc:()=>c});var i=r(5893),n=r(1151);const l={title:"Exclusion"},o=void 0,t={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v0.4.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v0.4.x/exclusion",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v0.4.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v0.4.x/customization"}},d={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function a(e){const s={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,n.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,i.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,i.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,i.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,i.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,i.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<EOF\n{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}\nEOF\n\n$ kubectl create configmap excluded --from-file=excluded=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,i.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,i.jsxs)(s.p,{children:["Exempting nodes with ",(0,i.jsx)(s.code,{children:"--filter-nodes"})," is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.jsx)(s.code,{children:"include"})," or ",(0,i.jsx)(s.code,{children:"exclude"})," from the cleanup process using the ",(0,i.jsx)(s.code,{children:"--filter-nodes"})," argument."]}),"\n",(0,i.jsx)(s.p,{children:(0,i.jsxs)(s.em,{children:["See ",(0,i.jsx)(s.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"Eraser Helm Chart"})," for more information on deployment."]})}),"\n",(0,i.jsxs)(s.p,{children:["Nodes with the selector ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"})," will be filtered accordingly."]}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsxs)(s.li,{children:["If ",(0,i.jsx)(s.code,{children:"include"})," is provided, eraser and collector pods will only be scheduled on nodes with the selector ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"}),"."]}),"\n",(0,i.jsxs)(s.li,{children:["If ",(0,i.jsx)(s.code,{children:"exclude"})," is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(s.p,{children:["Unless specified, the default value of ",(0,i.jsx)(s.code,{children:"--filter-nodes"})," is ",(0,i.jsx)(s.code,{children:"exclude"}),". Because Windows nodes are not supported, they will always be excluded regardless of the ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"})," label or the value of ",(0,i.jsx)(s.code,{children:"--filter-nodes"}),"."]}),"\n",(0,i.jsxs)(s.p,{children:["Additional node selectors can be provided through the ",(0,i.jsx)(s.code,{children:"--filter-nodes-selector"})," flag."]})]})}function h(e={}){const{wrapper:s}={...(0,n.a)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},1151:(e,s,r)=>{r.d(s,{Z:()=>t,a:()=>o});var i=r(7294);const n={},l=i.createContext(n);function o(e){const s=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function t(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),i.createElement(l.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/d7561401.2cac3291.js b/docs/assets/js/d7561401.2cac3291.js deleted file mode 100644 index f9a2bd6cb3..0000000000 --- a/docs/assets/js/d7561401.2cac3291.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9214],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),l=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(s,".").concat(d)]||m[d]||u[d]||o;return n?r.createElement(f,c(c({ref:t},p),{},{components:n})):r.createElement(f,c({ref:t},p))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=m;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var l=2;l<o;l++)c[l]=n[l];return r.createElement.apply(null,c)}return r.createElement.apply(null,n)}m.displayName="MDXCreateElement"},2077:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>c,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>l});var r=n(7462),a=(n(7294),n(3905));const o={title:"Custom Scanner"},c=void 0,i={unversionedId:"custom-scanner",id:"version-v1.0.x/custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.0.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v1.0.x/custom-scanner",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v1.0.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v1.0.x/trivy"}},s={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}],p={toc:l};function u(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"creating-a-custom-scanner"},"Creating a Custom Scanner"),(0,a.kt)("p",null,"To create a custom scanner for non-compliant images, use the following ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser-scanner-template/"},"template"),"."),(0,a.kt)("p",null,"In order to customize your scanner, start by creating a ",(0,a.kt)("inlineCode",{parentName:"p"},"NewImageProvider()"),". The ImageProvider interface can be found can be found ",(0,a.kt)("a",{parentName:"p",href:"../../pkg/scanners/template/scanner_template.go"},"here"),". "),(0,a.kt)("p",null,"The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,a.kt)("inlineCode",{parentName:"p"},"ReceiveImages()")," function. Process these images with your customized scanner and threshold, and use ",(0,a.kt)("inlineCode",{parentName:"p"},"SendImages()")," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,a.kt)("inlineCode",{parentName:"p"},"Finish()"),"."),(0,a.kt)("p",null,"When complete, provide your custom scanner image to Eraser in deployment."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/d7561401.72651373.js b/docs/assets/js/d7561401.72651373.js new file mode 100644 index 0000000000..4cf759754c --- /dev/null +++ b/docs/assets/js/d7561401.72651373.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9214],{4422:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>i,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var r=t(5893),s=t(1151);const o={title:"Custom Scanner"},a=void 0,c={id:"custom-scanner",title:"Custom Scanner",description:"Creating a Custom Scanner",source:"@site/versioned_docs/version-v1.0.x/custom-scanner.md",sourceDirName:".",slug:"/custom-scanner",permalink:"/eraser/docs/v1.0.x/custom-scanner",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Custom Scanner"},sidebar:"sidebar",previous:{title:"Releasing",permalink:"/eraser/docs/v1.0.x/releasing"},next:{title:"Trivy",permalink:"/eraser/docs/v1.0.x/trivy"}},i={},l=[{value:"Creating a Custom Scanner",id:"creating-a-custom-scanner",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",...(0,s.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h2,{id:"creating-a-custom-scanner",children:"Creating a Custom Scanner"}),"\n",(0,r.jsxs)(n.p,{children:["To create a custom scanner for non-compliant images, use the following ",(0,r.jsx)(n.a,{href:"https://github.com/eraser-dev/eraser-scanner-template/",children:"template"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["In order to customize your scanner, start by creating a ",(0,r.jsx)(n.code,{children:"NewImageProvider()"}),". The ImageProvider interface can be found can be found ",(0,r.jsx)(n.a,{href:"../../pkg/scanners/template/scanner_template.go",children:"here"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ",(0,r.jsx)(n.code,{children:"ReceiveImages()"})," function. Process these images with your customized scanner and threshold, and use ",(0,r.jsx)(n.code,{children:"SendImages()"})," to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling ",(0,r.jsx)(n.code,{children:"Finish()"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"When complete, provide your custom scanner image to Eraser in deployment."})]})}function u(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>c,a:()=>a});var r=t(7294);const s={},o=r.createContext(s);function a(e){const n=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/db59132a.6f50c1d0.js b/docs/assets/js/db59132a.6f50c1d0.js deleted file mode 100644 index cdaa8035a8..0000000000 --- a/docs/assets/js/db59132a.6f50c1d0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1619],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>u});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?l(Object(t),!0).forEach((function(n){r(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):l(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function o(e,n){if(null==e)return{};var t,a,r=function(e,n){if(null==e)return{};var t,a,r={},l=Object.keys(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(a=0;a<l.length;a++)t=l[a],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=a.createContext({}),c=function(e){var n=a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},p=function(e){var n=c(e.components);return a.createElement(s.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(t),u=r,k=m["".concat(s,".").concat(u)]||m[u]||d[u]||l;return t?a.createElement(k,i(i({ref:n},p),{},{components:t})):a.createElement(k,i({ref:n},p))}));function u(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,i=new Array(l);i[0]=m;var o={};for(var s in n)hasOwnProperty.call(n,s)&&(o[s]=n[s]);o.originalType=e,o.mdxType="string"==typeof e?e:r,i[1]=o;for(var c=2;c<l;c++)i[c]=t[c];return a.createElement.apply(null,i)}return a.createElement.apply(null,t)}m.displayName="MDXCreateElement"},8394:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>s,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var a=t(7462),r=(t(7294),t(3905));const l={title:"Quick Start"},i=void 0,o={unversionedId:"quick-start",id:"version-v1.1.x/quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.1.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v1.1.x/quick-start",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v1.1.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v1.1.x/architecture"}},s={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}],p={toc:c};function d(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."),(0,r.kt)("h2",{id:"deploy-a-daemonset"},"Deploy a DaemonSet"),(0,r.kt)("p",null,"After following the ",(0,r.kt)("a",{parentName:"p",href:"/eraser/docs/v1.1.x/installation"},"install instructions"),", we'll apply a demo ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,r.kt)("inlineCode",{parentName:"p"},"3.7.3")," tag will be used in this example. This is an image with a known critical vulnerability."),(0,r.kt)("p",null,"First, apply the ",(0,r.kt)("inlineCode",{parentName:"p"},"DaemonSet"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n")),(0,r.kt)("p",null,"Next, verify that the Pods are running or completed. After the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," Pods complete, you may see a ",(0,r.kt)("inlineCode",{parentName:"p"},"CrashLoopBackoff")," status. This is expected behavior from the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," image and can be ignored for the tutorial."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n")),(0,r.kt)("p",null,"Delete the DaemonSet:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl delete daemonset alpine\n")),(0,r.kt)("p",null,"Verify that the Pods have been deleted:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods\nNo resources found in default namespace.\n")),(0,r.kt)("p",null,"To verify that the ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine")," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."),(0,r.kt)("p",null,"List the nodes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n")),(0,r.kt)("p",null,"List the images then filter for ",(0,r.kt)("inlineCode",{parentName:"p"},"alpine"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n")),(0,r.kt)("h2",{id:"automatically-cleaning-images"},"Automatically Cleaning Images"),(0,r.kt)("p",null,"After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.scheduling.repeatInterval")," setting in the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". The default interval is 24 hours (",(0,r.kt)("inlineCode",{parentName:"p"},"24h"),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".'),(0,r.kt)("p",null,"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n")),(0,r.kt)("p",null,"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up. "),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.enabled")," value to ",(0,r.kt)("inlineCode",{parentName:"p"},"false")," using the ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options"},"configmap"),". In this case, each collector pod will hold 2 containers: collector and remover.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/db59132a.bdd9cb70.js b/docs/assets/js/db59132a.bdd9cb70.js new file mode 100644 index 0000000000..d8795bd0c2 --- /dev/null +++ b/docs/assets/js/db59132a.bdd9cb70.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1619],{9070:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var s=a(5893),t=a(1151);const r={title:"Quick Start"},i=void 0,l={id:"quick-start",title:"Quick Start",description:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.",source:"@site/versioned_docs/version-v1.1.x/quick-start.md",sourceDirName:".",slug:"/quick-start",permalink:"/eraser/docs/v1.1.x/quick-start",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Quick Start"},sidebar:"sidebar",previous:{title:"Installation",permalink:"/eraser/docs/v1.1.x/installation"},next:{title:"Architecture",permalink:"/eraser/docs/v1.1.x/architecture"}},o={},c=[{value:"Deploy a DaemonSet",id:"deploy-a-daemonset",level:2},{value:"Automatically Cleaning Images",id:"automatically-cleaning-images",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",code:"code",h2:"h2",p:"p",pre:"pre",...(0,t.a)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully."}),"\n",(0,s.jsx)(n.h2,{id:"deploy-a-daemonset",children:"Deploy a DaemonSet"}),"\n",(0,s.jsxs)(n.p,{children:["After following the ",(0,s.jsx)(n.a,{href:"/eraser/docs/v1.1.x/installation",children:"install instructions"}),", we'll apply a demo ",(0,s.jsx)(n.code,{children:"DaemonSet"}),". For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the ",(0,s.jsx)(n.code,{children:"3.7.3"})," tag will be used in this example. This is an image with a known critical vulnerability."]}),"\n",(0,s.jsxs)(n.p,{children:["First, apply the ",(0,s.jsx)(n.code,{children:"DaemonSet"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"cat <<EOF | kubectl apply -f -\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n name: alpine\nspec:\n selector:\n matchLabels:\n app: alpine\n template:\n metadata:\n labels:\n app: alpine\n spec:\n containers:\n - name: alpine\n image: docker.io/library/alpine:3.7.3\nEOF\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Next, verify that the Pods are running or completed. After the ",(0,s.jsx)(n.code,{children:"alpine"})," Pods complete, you may see a ",(0,s.jsx)(n.code,{children:"CrashLoopBackoff"})," status. This is expected behavior from the ",(0,s.jsx)(n.code,{children:"alpine"})," image and can be ignored for the tutorial."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\nalpine-2gh9c 1/1 Running 1 (3s ago) 6s\nalpine-hljp9 0/1 Completed 1 (3s ago) 6s\n"})}),"\n",(0,s.jsx)(n.p,{children:"Delete the DaemonSet:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl delete daemonset alpine\n"})}),"\n",(0,s.jsx)(n.p,{children:"Verify that the Pods have been deleted:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods\nNo resources found in default namespace.\n"})}),"\n",(0,s.jsxs)(n.p,{children:["To verify that the ",(0,s.jsx)(n.code,{children:"alpine"})," images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly."]}),"\n",(0,s.jsx)(n.p,{children:"List the nodes:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\nkind-control-plane Ready control-plane 45m v1.24.0\nkind-worker Ready <none> 45m v1.24.0\nkind-worker2 Ready <none> 44m v1.24.0\n"})}),"\n",(0,s.jsxs)(n.p,{children:["List the images then filter for ",(0,s.jsx)(n.code,{children:"alpine"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\ndocker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\ndocker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed\n\n"})}),"\n",(0,s.jsx)(n.h2,{id:"automatically-cleaning-images",children:"Automatically Cleaning Images"}),"\n",(0,s.jsxs)(n.p,{children:["After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the ",(0,s.jsx)(n.code,{children:"manager.scheduling.repeatInterval"})," setting in the ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". The default interval is 24 hours (",(0,s.jsx)(n.code,{children:"24h"}),'). Valid time units are "ns", "us" (or "\xb5s"), "ms", "s", "m", "h".']}),"\n",(0,s.jsx)(n.p,{children:"Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m\neraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m\neraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m\n"})}),"\n",(0,s.jsx)(n.p,{children:"The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up."}),"\n",(0,s.jsxs)(n.blockquote,{children:["\n",(0,s.jsxs)(n.p,{children:["If you want to remove all the images periodically, you can skip the scanner container by setting the ",(0,s.jsx)(n.code,{children:"components.scanner.enabled"})," value to ",(0,s.jsx)(n.code,{children:"false"})," using the ",(0,s.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#detailed-options",children:"configmap"}),". In this case, each collector pod will hold 2 containers: collector and remover."]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\nNAMESPACE NAME READY STATUS RESTARTS AGE\neraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s\neraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s\neraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s\neraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.a)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1151:(e,n,a)=>{a.d(n,{Z:()=>l,a:()=>i});var s=a(7294);const t={},r=s.createContext(t);function i(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/dbbf7db4.ad052b4c.js b/docs/assets/js/dbbf7db4.ad052b4c.js new file mode 100644 index 0000000000..073d818308 --- /dev/null +++ b/docs/assets/js/dbbf7db4.ad052b4c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5245],{8134:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>r,contentTitle:()=>s,default:()=>f,frontMatter:()=>d,metadata:()=>i,toc:()=>u});var n=t(5893),c=t(1151);const d={title:"Code of Conduct"},s=void 0,i={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.0.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v1.0.x/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v1.0.x/contributing"}},r={},u=[];function a(e){const o={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["This project has adopted the ",(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"Resources:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(o.li,{children:(0,n.jsx)(o.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:o}={...(0,c.a)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,o,t)=>{t.d(o,{Z:()=>i,a:()=>s});var n=t(7294);const c={},d=n.createContext(c);function s(e){const o=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function i(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:s(e.components),n.createElement(d.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/dbbf7db4.c7332918.js b/docs/assets/js/dbbf7db4.c7332918.js deleted file mode 100644 index 4ef464a840..0000000000 --- a/docs/assets/js/dbbf7db4.c7332918.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5245],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l<c;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},9209:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"version-v1.0.x/code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/versioned_docs/version-v1.0.x/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/v1.0.x/code-of-conduct",draft:!1,tags:[],version:"v1.0.x",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/v1.0.x/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/dc9281b9.7ca1886c.js b/docs/assets/js/dc9281b9.7ca1886c.js new file mode 100644 index 0000000000..38a63232a3 --- /dev/null +++ b/docs/assets/js/dc9281b9.7ca1886c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[895],{9796:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var t=r(5893),s=r(1151);const o={title:"Customization"},i=void 0,a={id:"customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.1.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v1.1.x/customization",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v1.1.x/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/v1.1.x/metrics"}},c={},l=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"kubectl edit configmap --namespace eraser-system eraser-manager-config\n"})}),"\n",(0,t.jsx)(n.p,{children:"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."}),"\n",(0,t.jsx)(n.h2,{id:"key-concepts",children:"Key Concepts"}),"\n",(0,t.jsx)(n.h3,{id:"basic-architecture",children:"Basic architecture"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.em,{children:"manager"})," runs as a pod in your cluster and manages ",(0,t.jsx)(n.em,{children:"ImageJobs"}),". Think of\nan ",(0,t.jsx)(n.em,{children:"ImageJob"})," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,t.jsx)(n.em,{children:"ImageJob"})," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Assessment"}),"\n",(0,t.jsx)(n.li,{children:"Removal."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"scheduling",children:"Scheduling"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," can either be created on-demand (see ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/manual-removal",children:"Manual Removal"}),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."]}),"\n",(0,t.jsx)(n.h3,{id:"fault-tolerance",children:"Fault Tolerance"}),"\n",(0,t.jsxs)(n.p,{children:["Because an ",(0,t.jsx)(n.em,{children:"ImageJob"})," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,t.jsx)(n.code,{children:"manager.imageJob.successRatio"})," property to\n",(0,t.jsx)(n.code,{children:"1.0"}),". If 75% success sounds good to you, set it to ",(0,t.jsx)(n.code,{children:"0.75"}),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,t.jsx)(n.em,{children:"ImageJob"})," report success, the job as\na whole will be marked as a failure."]}),"\n",(0,t.jsxs)(n.p,{children:["This is mainly to help diagnose error conditions. As such, you can set\n",(0,t.jsx)(n.code,{children:"manager.imageJob.cleanup.delayOnFailure"})," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."]}),"\n",(0,t.jsx)(n.h3,{id:"excluding-nodes",children:"Excluding Nodes"}),"\n",(0,t.jsxs)(n.p,{children:["For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,t.jsx)(n.code,{children:"eraser.sh/cleanup.filter"}),", but you can configure the behavior with\nthe options under ",(0,t.jsx)(n.code,{children:"manager.nodeFilter"}),". The ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"})," provides more detail."]}),"\n",(0,t.jsx)(n.h3,{id:"configuring-components",children:"Configuring Components"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Collection (What is on the node?)"}),"\n",(0,t.jsx)(n.li,{children:"Scanning (What images conform to the policy I've provided?)"}),"\n",(0,t.jsx)(n.li,{children:"Removal (Remove images based on the results of the above)"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,t.jsx)(n.em,{children:"ImageJobs"})," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["The collector and/or scanner ",(0,t.jsx)(n.code,{children:"components"})," are enabled, AND"]}),"\n",(0,t.jsxs)(n.li,{children:["The job was ",(0,t.jsx)(n.em,{children:"not"})," triggered manually by creating an ",(0,t.jsx)(n.em,{children:"ImageList"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"swapping-out-components",children:"Swapping out components"}),"\n",(0,t.jsxs)(n.p,{children:["The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,t.jsx)(n.code,{children:"components.<component>.image.repo"})," and ",(0,t.jsx)(n.code,{children:"components.<component>.image.tag"}),",\nwhere ",(0,t.jsx)(n.code,{children:"<component>"})," is one of ",(0,t.jsx)(n.code,{children:"collector"}),", ",(0,t.jsx)(n.code,{children:"scanner"}),", or ",(0,t.jsx)(n.code,{children:"remover"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"universal-options",children:"Universal Options"}),"\n",(0,t.jsxs)(n.p,{children:["The following portions of the configmap apply no matter how you spawn your\n",(0,t.jsx)(n.em,{children:"ImageJob"}),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'manager:\n runtime: containerd\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n'})}),"\n",(0,t.jsx)(n.h2,{id:"component-options",children:"Component Options"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n"})}),"\n",(0,t.jsx)(n.h2,{id:"scanner-options",children:"Scanner Options"}),"\n",(0,t.jsxs)(n.p,{children:["These options can be provided to ",(0,t.jsx)(n.code,{children:"components.scanner.config"}),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."]}),"\n",(0,t.jsxs)(n.p,{children:["Below are the values recognized by the provided ",(0,t.jsx)(n.code,{children:"eraser-trivy-scanner"})," image.\nValues provided below are the defaults."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more invormation\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n"})}),"\n",(0,t.jsx)(n.h2,{id:"detailed-options",children:"Detailed Options"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Option"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Default"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.runtime"}),(0,t.jsx)(n.td,{children:"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."}),(0,t.jsx)(n.td,{children:"containerd"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.otlpEndpoint"}),(0,t.jsx)(n.td,{children:"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.logLevel"}),(0,t.jsx)(n.td,{children:"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."}),(0,t.jsx)(n.td,{children:"info"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.repeatInterval"}),(0,t.jsxs)(n.td,{children:["Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,t.jsx)(n.em,{children:"ImageJob"})," at the interval provided."]}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.beginImmediately"}),(0,t.jsxs)(n.td,{children:["If set to true, the fist ",(0,t.jsx)(n.em,{children:"ImageJob"})," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."]}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.enabled"}),(0,t.jsxs)(n.td,{children:["Whether to enable profiling for the manager's containers. This is for debugging with ",(0,t.jsx)(n.code,{children:"go tool pprof"}),"."]}),(0,t.jsx)(n.td,{children:"false"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.port"}),(0,t.jsx)(n.td,{children:"The port on which to expose the profiling endpoint."}),(0,t.jsx)(n.td,{children:"6060"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.successRatio"}),(0,t.jsx)(n.td,{children:"The ratio of successful image jobs required before a cleanup is performed."}),(0,t.jsx)(n.td,{children:"1.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnSuccess"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a successful image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"0s"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnFailure"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a failed image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.pullSecrets"}),(0,t.jsx)(n.td,{children:"The image pull secrets to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.priorityClassName"}),(0,t.jsx)(n.td,{children:"The priority class to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.type"}),(0,t.jsx)(n.td,{children:'The type of node filter to use. Must be either "exclude" or "include".'}),(0,t.jsx)(n.td,{children:"exclude"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.selectors"}),(0,t.jsx)(n.td,{children:"A list of selectors used to filter nodes."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the collector component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the collector image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/collector"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the collector image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the collector container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the collector container."}),(0,t.jsx)(n.td,{children:"7m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the scanner component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the scanner image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the scanner image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the scanner container."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the scanner container."}),(0,t.jsx)(n.td,{children:"1000m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"2Gi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.config"}),(0,t.jsx)(n.td,{children:"The configuration to pass to the scanner container, as a YAML string."}),(0,t.jsx)(n.td,{children:"See YAML below"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the remover image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/remover"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the remover image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the remover container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the remover container."}),(0,t.jsx)(n.td,{children:"0"})]})]})]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>i});var t=r(7294);const s={},o=t.createContext(s);function i(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/dc9281b9.8b8ee3c8.js b/docs/assets/js/dc9281b9.8b8ee3c8.js deleted file mode 100644 index 9eebcf6a3e..0000000000 --- a/docs/assets/js/dc9281b9.8b8ee3c8.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[895],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var m=a.createContext({}),s=function(e){var t=a.useContext(m),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return a.createElement(m.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,m=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),c=s(n),d=r,g=c["".concat(m,".").concat(d)]||c[d]||u[d]||o;return n?a.createElement(g,l(l({ref:t},p),{},{components:n})):a.createElement(g,l({ref:t},p))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=c;var i={};for(var m in t)hasOwnProperty.call(t,m)&&(i[m]=t[m]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var s=2;s<o;s++)l[s]=n[s];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}c.displayName="MDXCreateElement"},8561:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>m,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>s});var a=n(7462),r=(n(7294),n(3905));const o={title:"Customization"},l=void 0,i={unversionedId:"customization",id:"version-v1.1.x/customization",title:"Customization",description:"Overview",source:"@site/versioned_docs/version-v1.1.x/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/v1.1.x/customization",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/v1.1.x/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/v1.1.x/metrics"}},m={},s=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}],p={toc:s};function u(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl edit configmap --namespace eraser-system eraser-manager-config\n")),(0,r.kt)("p",null,"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."),(0,r.kt)("h2",{id:"key-concepts"},"Key Concepts"),(0,r.kt)("h3",{id:"basic-architecture"},"Basic architecture"),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"manager")," runs as a pod in your cluster and manages ",(0,r.kt)("em",{parentName:"p"},"ImageJobs"),". Think of\nan ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Assessment"),(0,r.kt)("li",{parentName:"ol"},"Removal.")),(0,r.kt)("h3",{id:"scheduling"},"Scheduling"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," can either be created on-demand (see ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/manual-removal"},"Manual Removal"),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."),(0,r.kt)("h3",{id:"fault-tolerance"},"Fault Tolerance"),(0,r.kt)("p",null,"Because an ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.successRatio")," property to\n",(0,r.kt)("inlineCode",{parentName:"p"},"1.0"),". If 75% success sounds good to you, set it to ",(0,r.kt)("inlineCode",{parentName:"p"},"0.75"),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," report success, the job as\na whole will be marked as a failure."),(0,r.kt)("p",null,"This is mainly to help diagnose error conditions. As such, you can set\n",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.cleanup.delayOnFailure")," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."),(0,r.kt)("h3",{id:"excluding-nodes"},"Excluding Nodes"),(0,r.kt)("p",null,"For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter"),", but you can configure the behavior with\nthe options under ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.nodeFilter"),". The ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table")," provides more detail."),(0,r.kt)("h3",{id:"configuring-components"},"Configuring Components"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Collection (What is on the node?)"),(0,r.kt)("li",{parentName:"ol"},"Scanning (What images conform to the policy I've provided?)"),(0,r.kt)("li",{parentName:"ol"},"Removal (Remove images based on the results of the above)")),(0,r.kt)("p",null,"Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,r.kt)("em",{parentName:"p"},"ImageJobs")," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"The collector and/or scanner ",(0,r.kt)("inlineCode",{parentName:"li"},"components")," are enabled, AND"),(0,r.kt)("li",{parentName:"ol"},"The job was ",(0,r.kt)("em",{parentName:"li"},"not")," triggered manually by creating an ",(0,r.kt)("em",{parentName:"li"},"ImageList"),".")),(0,r.kt)("h3",{id:"swapping-out-components"},"Swapping out components"),(0,r.kt)("p",null,"The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.repo")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.tag"),",\nwhere ",(0,r.kt)("inlineCode",{parentName:"p"},"<component>")," is one of ",(0,r.kt)("inlineCode",{parentName:"p"},"collector"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"scanner"),", or ",(0,r.kt)("inlineCode",{parentName:"p"},"remover"),"."),(0,r.kt)("h2",{id:"universal-options"},"Universal Options"),(0,r.kt)("p",null,"The following portions of the configmap apply no matter how you spawn your\n",(0,r.kt)("em",{parentName:"p"},"ImageJob"),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'manager:\n runtime: containerd\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n')),(0,r.kt)("h2",{id:"component-options"},"Component Options"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n")),(0,r.kt)("h2",{id:"scanner-options"},"Scanner Options"),(0,r.kt)("p",null,"These options can be provided to ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.config"),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."),(0,r.kt)("p",null,"Below are the values recognized by the provided ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-trivy-scanner")," image.\nValues provided below are the defaults."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more invormation\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n")),(0,r.kt)("h2",{id:"detailed-options"},"Detailed Options"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Option"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"),(0,r.kt)("th",{parentName:"tr",align:null},"Default"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."),(0,r.kt)("td",{parentName:"tr",align:null},"containerd")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.otlpEndpoint"),(0,r.kt)("td",{parentName:"tr",align:null},"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.logLevel"),(0,r.kt)("td",{parentName:"tr",align:null},"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."),(0,r.kt)("td",{parentName:"tr",align:null},"info")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.repeatInterval"),(0,r.kt)("td",{parentName:"tr",align:null},"Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," at the interval provided."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.beginImmediately"),(0,r.kt)("td",{parentName:"tr",align:null},"If set to true, the fist ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable profiling for the manager's containers. This is for debugging with ",(0,r.kt)("inlineCode",{parentName:"td"},"go tool pprof"),"."),(0,r.kt)("td",{parentName:"tr",align:null},"false")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.port"),(0,r.kt)("td",{parentName:"tr",align:null},"The port on which to expose the profiling endpoint."),(0,r.kt)("td",{parentName:"tr",align:null},"6060")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.successRatio"),(0,r.kt)("td",{parentName:"tr",align:null},"The ratio of successful image jobs required before a cleanup is performed."),(0,r.kt)("td",{parentName:"tr",align:null},"1.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnSuccess"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a successful image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"0s")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnFailure"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a failed image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.pullSecrets"),(0,r.kt)("td",{parentName:"tr",align:null},"The image pull secrets to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.priorityClassName"),(0,r.kt)("td",{parentName:"tr",align:null},"The priority class to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.type"),(0,r.kt)("td",{parentName:"tr",align:null},'The type of node filter to use. Must be either "exclude" or "include".'),(0,r.kt)("td",{parentName:"tr",align:null},"exclude")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.selectors"),(0,r.kt)("td",{parentName:"tr",align:null},"A list of selectors used to filter nodes."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the collector component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/collector")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"7m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the scanner component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/eraser-trivy-scanner")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"1000m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"2Gi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.config"),(0,r.kt)("td",{parentName:"tr",align:null},"The configuration to pass to the scanner container, as a YAML string."),(0,r.kt)("td",{parentName:"tr",align:null},"See YAML below")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/remover")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"0")))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/dea0f9ea.313a6052.js b/docs/assets/js/dea0f9ea.313a6052.js deleted file mode 100644 index f9ae8be9a1..0000000000 --- a/docs/assets/js/dea0f9ea.313a6052.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6352],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>s});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},c=Object.keys(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r<c.length;r++)n=c[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var u=r.createContext({}),l=function(e){var t=r.useContext(u),n=t;return e&&(n="function"==typeof e?e(t):a(a({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(u.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},f=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,c=e.originalType,u=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),f=l(n),s=o,m=f["".concat(u,".").concat(s)]||f[s]||d[s]||c;return n?r.createElement(m,a(a({ref:t},p),{},{components:n})):r.createElement(m,a({ref:t},p))}));function s(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var c=n.length,a=new Array(c);a[0]=f;var i={};for(var u in t)hasOwnProperty.call(t,u)&&(i[u]=t[u]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var l=2;l<c;l++)a[l]=n[l];return r.createElement.apply(null,a)}return r.createElement.apply(null,n)}f.displayName="MDXCreateElement"},6853:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>a,default:()=>d,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var r=n(7462),o=(n(7294),n(3905));const c={title:"Code of Conduct"},a=void 0,i={unversionedId:"code-of-conduct",id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/docs/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/next/code-of-conduct",draft:!1,tags:[],version:"current",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/next/contributing"}},u={},l=[],p={toc:l};function d(e){let{components:t,...n}=e;return(0,o.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"This project has adopted the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct"),"."),(0,o.kt)("p",null,"Resources:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"CNCF Code of Conduct")),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("a",{parentName:"li",href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md"},"Code of Conduct Reporting"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/dea0f9ea.7a05a9de.js b/docs/assets/js/dea0f9ea.7a05a9de.js new file mode 100644 index 0000000000..1b122e4f0c --- /dev/null +++ b/docs/assets/js/dea0f9ea.7a05a9de.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6352],{3427:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>i,contentTitle:()=>r,default:()=>f,frontMatter:()=>d,metadata:()=>s,toc:()=>u});var n=o(5893),c=o(1151);const d={title:"Code of Conduct"},r=void 0,s={id:"code-of-conduct",title:"Code of Conduct",description:"This project has adopted the CNCF Code of Conduct.",source:"@site/docs/code-of-conduct.md",sourceDirName:".",slug:"/code-of-conduct",permalink:"/eraser/docs/next/code-of-conduct",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Code of Conduct"},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/eraser/docs/next/contributing"}},i={},u=[];function a(e){const t={a:"a",li:"li",p:"p",ul:"ul",...(0,c.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["This project has adopted the ",(0,n.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"}),"."]}),"\n",(0,n.jsx)(t.p,{children:"Resources:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"CNCF Code of Conduct"})}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/cncf/foundation/blob/main/code-of-conduct.md",children:"Code of Conduct Reporting"})}),"\n"]})]})}function f(e={}){const{wrapper:t}={...(0,c.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},1151:(e,t,o)=>{o.d(t,{Z:()=>s,a:()=>r});var n=o(7294);const c={},d=n.createContext(c);function r(e){const t=n.useContext(d);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:r(e.components),n.createElement(d.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e1b2cf59.5eb99ea6.js b/docs/assets/js/e1b2cf59.5eb99ea6.js new file mode 100644 index 0000000000..589855cd65 --- /dev/null +++ b/docs/assets/js/e1b2cf59.5eb99ea6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2023],{3748:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var n=r(5893),i=r(1151);const o={title:"Trivy"},s=void 0,a={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.1.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v1.1.x/trivy",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v1.1.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v1.1.x/faq"}},c={},d=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function v(e){const t={a:"a",h2:"h2",p:"p",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,n.jsxs)(t.p,{children:["The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,n.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"Customization"})," for more details on configuring the scanner."]})]})}function u(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(v,{...e})}):v(e)}},1151:(e,t,r)=>{r.d(t,{Z:()=>a,a:()=>s});var n=r(7294);const i={},o=n.createContext(i);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e1b2cf59.b8a8ffb4.js b/docs/assets/js/e1b2cf59.b8a8ffb4.js deleted file mode 100644 index 3f77892340..0000000000 --- a/docs/assets/js/e1b2cf59.b8a8ffb4.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2023],{3905:(e,r,t)=>{t.d(r,{Zo:()=>l,kt:()=>f});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?i(Object(t),!0).forEach((function(r){o(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function c(e,r){if(null==e)return{};var t,n,o=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},l=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},v=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),v=p(t),f=o,y=v["".concat(s,".").concat(f)]||v[f]||u[f]||i;return t?n.createElement(y,a(a({ref:r},l),{},{components:t})):n.createElement(y,a({ref:r},l))}));function f(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=v;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p<i;p++)a[p]=t[p];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}v.displayName="MDXCreateElement"},1766:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i={title:"Trivy"},a=void 0,c={unversionedId:"trivy",id:"version-v1.1.x/trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v1.1.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v1.1.x/trivy",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v1.1.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v1.1.x/faq"}},s={},p=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],l={toc:p};function u(e){let{components:r,...t}=e;return(0,o.kt)("wrapper",(0,n.Z)({},l,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,o.kt)("p",null,"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"Customization")," for more details on configuring the scanner."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/e36340b6.4feb6f73.js b/docs/assets/js/e36340b6.4feb6f73.js new file mode 100644 index 0000000000..c86ad4e854 --- /dev/null +++ b/docs/assets/js/e36340b6.4feb6f73.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9722],{1001:(e,s,i)=>{i.r(s),i.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>t,metadata:()=>a,toc:()=>l});var r=i(5893),n=i(1151);const t={title:"Exclusion"},o=void 0,a={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.1.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v1.1.x/exclusion",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v1.1.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v1.1.x/customization"}},c={},l=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function d(e){const s={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,n.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,r.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,r.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,r.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,r.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,r.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,r.jsx)(s.pre,{children:(0,r.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,r.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,r.jsxs)(s.p,{children:["Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,r.jsx)(s.code,{children:"include"})," or ",(0,r.jsx)(s.code,{children:"exclude"})," from the cleanup process using the configmap. For more information, see the section on ",(0,r.jsx)(s.a,{href:"https://eraser-dev.github.io/eraser/docs/customization",children:"customization"}),"."]})]})}function u(e={}){const{wrapper:s}={...(0,n.a)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,s,i)=>{i.d(s,{Z:()=>a,a:()=>o});var r=i(7294);const n={},t=r.createContext(n);function o(e){const s=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function a(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),r.createElement(t.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e36340b6.8972753a.js b/docs/assets/js/e36340b6.8972753a.js deleted file mode 100644 index 1a44cef079..0000000000 --- a/docs/assets/js/e36340b6.8972753a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[9722],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function o(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?o(Object(t),!0).forEach((function(r){i(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):o(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function s(e,r){if(null==e)return{};var t,n,i=function(e,r){if(null==e)return{};var t,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)t=o[n],r.indexOf(t)>=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)t=o[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=n.createContext({}),c=function(e){var r=n.useContext(l),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},p=function(e){var r=c(e.components);return n.createElement(l.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(t),m=i,f=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return t?n.createElement(f,a(a({ref:r},p),{},{components:t})):n.createElement(f,a({ref:r},p))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var o=t.length,a=new Array(o);a[0]=d;var s={};for(var l in r)hasOwnProperty.call(r,l)&&(s[l]=r[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,a[1]=s;for(var c=2;c<o;c++)a[c]=t[c];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}d.displayName="MDXCreateElement"},1635:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var n=t(7462),i=(t(7294),t(3905));const o={title:"Exclusion"},a=void 0,s={unversionedId:"exclusion",id:"version-v1.1.x/exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v1.1.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v1.1.x/exclusion",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v1.1.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v1.1.x/customization"}},l={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],p={toc:c};function u(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<"EOF"\n{\n "excluded": [\n "docker.io/library/*",\n "ghcr.io/eraser-dev/test:latest"\n ]\n}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the configmap. For more information, see the section on ",(0,i.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization"},"customization"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/e3d8f98f.a2c52a4d.js b/docs/assets/js/e3d8f98f.a2c52a4d.js new file mode 100644 index 0000000000..1b44ed5b39 --- /dev/null +++ b/docs/assets/js/e3d8f98f.a2c52a4d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6236],{9899:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>a,metadata:()=>i,toc:()=>l});var r=n(5893),o=n(1151);const a={title:"Metrics"},s=void 0,i={id:"metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.2.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/v1.2.x/metrics",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v1.2.x/customization"},next:{title:"Setup",permalink:"/eraser/docs/v1.2.x/setup"}},c={},l=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}];function d(e){const t={a:"a",code:"code",h4:"h4",p:"p",pre:"pre",...(0,o.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:["To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,r.jsx)(t.a,{href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml",children:"otelcollector.yaml"}),", and the endpoint can be specified using the ",(0,r.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options",children:"configmap"}),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at '",(0,r.jsx)(t.a,{href:"http://localhost:8889/metrics",children:"http://localhost:8889/metrics"}),"', but a separate exporter can also be configured."]}),"\n",(0,r.jsx)(t.p,{children:"Below is the list of metrics provided by Eraser per run:"}),"\n",(0,r.jsx)(t.h4,{id:"eraser",children:"Eraser"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n\t- name: images_removed_run_total\n\t\t- description: Total images removed by eraser\n"})}),"\n",(0,r.jsx)(t.h4,{id:"scanner",children:"Scanner"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: vulnerable_images_run_total\n \t- description: Total vulnerable images detected\n"})}),"\n",(0,r.jsx)(t.h4,{id:"imagejob",children:"ImageJob"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:"- count\n - name: imagejob_run_total\n \t- description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n \t- description: Total pods completed\n - name: pods_failed_run_total\n \t- description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n \t- description: Total time for ImageJobs scheduled to complete\n"})})]})}function m(e={}){const{wrapper:t}={...(0,o.a)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>i,a:()=>s});var r=n(7294);const o={},a=r.createContext(o);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e3d8f98f.c2802ab1.js b/docs/assets/js/e3d8f98f.c2802ab1.js deleted file mode 100644 index 5f84fa115f..0000000000 --- a/docs/assets/js/e3d8f98f.c2802ab1.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6236],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>d});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,o=function(e,t){if(null==e)return{};var r,n,o={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(r),d=o,f=u["".concat(c,".").concat(d)]||u[d]||m[d]||a;return r?n.createElement(f,i(i({ref:t},p),{},{components:r})):n.createElement(f,i({ref:t},p))}));function d(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:o,i[1]=l;for(var s=2;s<a;s++)i[s]=r[s];return n.createElement.apply(null,i)}return n.createElement.apply(null,r)}u.displayName="MDXCreateElement"},6040:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={title:"Metrics"},i=void 0,l={unversionedId:"metrics",id:"version-v1.2.x/metrics",title:"Metrics",description:"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http8889/metrics', but a separate exporter can also be configured.",source:"@site/versioned_docs/version-v1.2.x/metrics.md",sourceDirName:".",slug:"/metrics",permalink:"/eraser/docs/v1.2.x/metrics",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Metrics"},sidebar:"sidebar",previous:{title:"Customization",permalink:"/eraser/docs/v1.2.x/customization"},next:{title:"Setup",permalink:"/eraser/docs/v1.2.x/setup"}},c={},s=[{value:"Eraser",id:"eraser",level:4},{value:"Scanner",id:"scanner",level:4},{value:"ImageJob",id:"imagejob",level:4}],p={toc:s};function m(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/eraser-dev/eraser/blob/main/test/e2e/test-data/otelcollector.yaml"},"otelcollector.yaml"),", and the endpoint can be specified using the ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#universal-options"},"configmap"),". In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured."),(0,o.kt)("p",null,"Below is the list of metrics provided by Eraser per run:"),(0,o.kt)("h4",{id:"eraser"},"Eraser"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: images_removed_run_total\n - description: Total images removed by eraser\n")),(0,o.kt)("h4",{id:"scanner"},"Scanner"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: vulnerable_images_run_total\n - description: Total vulnerable images detected\n")),(0,o.kt)("h4",{id:"imagejob"},"ImageJob"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-yaml"},"- count\n - name: imagejob_run_total\n - description: Total ImageJobs scheduled\n - name: pods_completed_run_total\n - description: Total pods completed\n - name: pods_failed_run_total\n - description: Total pods failed\n- summary\n - name: imagejob_duration_run_seconds\n - description: Total time for ImageJobs scheduled to complete\n")))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/e7fdf6d9.94d9b31c.js b/docs/assets/js/e7fdf6d9.94d9b31c.js new file mode 100644 index 0000000000..d41506e46d --- /dev/null +++ b/docs/assets/js/e7fdf6d9.94d9b31c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[643],{2016:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>o,contentTitle:()=>i,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var r=n(5893),t=n(1151);const a={},i="Release Management",l={id:"release-management",title:"Release Management",description:"Overview",source:"@site/versioned_docs/version-v1.3.x/release-management.md",sourceDirName:".",slug:"/release-management",permalink:"/eraser/docs/release-management",draft:!1,unlisted:!1,tags:[],version:"v1.3.x",frontMatter:{}},o={},c=[{value:"Overview",id:"overview",level:2},{value:"Legend",id:"legend",level:2},{value:"Release Versioning",id:"release-versioning",level:2},{value:"Supported Releases",id:"supported-releases",level:2},{value:"Supported Kubernetes Versions",id:"supported-kubernetes-versions",level:2},{value:"Acknowledgement",id:"acknowledgement",level:2}];function d(e){const s={a:"a",em:"em",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h1,{id:"release-management",children:"Release Management"}),"\n",(0,r.jsx)(s.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(s.p,{children:"This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades."}),"\n",(0,r.jsx)(s.h2,{id:"legend",children:"Legend"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"X.Y.Z"})," refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Breaking changes"})," refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Milestone"})," should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Patch releases"})," refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility."]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"Test gates"})," should include soak tests and upgrade tests from the last minor version."]}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"release-versioning",children:"Release Versioning"}),"\n",(0,r.jsxs)(s.p,{children:["All releases will be of the form ",(0,r.jsx)(s.em,{children:"vX.Y.Z"})," where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning."]}),"\n",(0,r.jsx)(s.p,{children:"The rest of the doc will cover the release process for the following kinds of releases:"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Major Releases"})}),"\n",(0,r.jsx)(s.p,{children:"No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project"}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Minor Releases"})}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["X.Y.0-alpha.W, W >= 0 (Branch : main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released as needed before we cut a beta X.Y release"}),"\n",(0,r.jsx)(s.li,{children:"Alpha release, cut from master branch"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.li,{children:["X.Y.0-beta.W, W >= 0 (Branch : main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released as needed before we cut a stable X.Y release"}),"\n",(0,r.jsx)(s.li,{children:"More stable than the alpha release to signal users to test things out"}),"\n",(0,r.jsx)(s.li,{children:"Beta release, cut from master branch"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.li,{children:["X.Y.0-rc.W, W >= 0 (Branch : main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released as needed before we cut a stable X.Y release"}),"\n",(0,r.jsx)(s.li,{children:"soak for ~ 2 weeks before cutting a stable release"}),"\n",(0,r.jsx)(s.li,{children:"Release candidate release, cut from master branch"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.li,{children:["X.Y.0 (Branch: main)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"Released every ~ 3 months"}),"\n",(0,r.jsx)(s.li,{children:"Stable release, cut from master when X.Y milestone is complete"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:(0,r.jsx)(s.strong,{children:"Patch Releases"})}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed)","\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsx)(s.li,{children:"No breaking changes"}),"\n",(0,r.jsx)(s.li,{children:"Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches."}),"\n",(0,r.jsx)(s.li,{children:"Patch release, cut from a release-X.Y branch"}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"supported-releases",children:"Supported Releases"}),"\n",(0,r.jsx)(s.p,{children:"Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed."}),"\n",(0,r.jsx)(s.p,{children:"We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible."}),"\n",(0,r.jsx)(s.p,{children:'We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.'}),"\n",(0,r.jsx)(s.h2,{id:"supported-kubernetes-versions",children:"Supported Kubernetes Versions"}),"\n",(0,r.jsxs)(s.p,{children:["Eraser is assumed to be compatible with the ",(0,r.jsx)(s.a,{href:"https://kubernetes.io/releases/patch-releases/#detailed-release-history-for-active-branches",children:"current Kubernetes Supported Versions"})," per ",(0,r.jsx)(s.a,{href:"https://kubernetes.io/releases/version-skew-policy/",children:"Kubernetes Supported Versions policy"}),"."]}),"\n",(0,r.jsxs)(s.p,{children:["For example, if Eraser ",(0,r.jsx)(s.em,{children:"supported"})," versions are v1.2 and v1.1, and Kubernetes ",(0,r.jsx)(s.em,{children:"supported"})," versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time."]}),"\n",(0,r.jsx)(s.p,{children:"If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk."}),"\n",(0,r.jsx)(s.h2,{id:"acknowledgement",children:"Acknowledgement"}),"\n",(0,r.jsx)(s.p,{children:"This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm."})]})}function h(e={}){const{wrapper:s}={...(0,t.a)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,s,n)=>{n.d(s,{Z:()=>l,a:()=>i});var r=n(7294);const t={},a=r.createContext(t);function i(e){const s=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),r.createElement(a.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e7fdf6d9.de866fbb.js b/docs/assets/js/e7fdf6d9.de866fbb.js deleted file mode 100644 index 97b91cc2b7..0000000000 --- a/docs/assets/js/e7fdf6d9.de866fbb.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[643],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var a=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function s(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?s(Object(r),!0).forEach((function(t){n(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):s(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t){if(null==e)return{};var r,a,n=function(e,t){if(null==e)return{};var r,a,n={},s=Object.keys(e);for(a=0;a<s.length;a++)r=s[a],t.indexOf(r)>=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a<s.length;a++)r=s[a],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var i=a.createContext({}),p=function(e){var t=a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=p(e.components);return a.createElement(i.Provider,{value:t},e.children)},c={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,s=e.originalType,i=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),m=p(r),d=n,h=m["".concat(i,".").concat(d)]||m[d]||c[d]||s;return r?a.createElement(h,l(l({ref:t},u),{},{components:r})):a.createElement(h,l({ref:t},u))}));function d(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var s=r.length,l=new Array(s);l[0]=m;var o={};for(var i in t)hasOwnProperty.call(t,i)&&(o[i]=t[i]);o.originalType=e,o.mdxType="string"==typeof e?e:n,l[1]=o;for(var p=2;p<s;p++)l[p]=r[p];return a.createElement.apply(null,l)}return a.createElement.apply(null,r)}m.displayName="MDXCreateElement"},7016:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>c,frontMatter:()=>s,metadata:()=>o,toc:()=>p});var a=r(7462),n=(r(7294),r(3905));const s={},l="Release Management",o={unversionedId:"release-management",id:"version-v1.3.x/release-management",title:"Release Management",description:"Overview",source:"@site/versioned_docs/version-v1.3.x/release-management.md",sourceDirName:".",slug:"/release-management",permalink:"/eraser/docs/release-management",draft:!1,tags:[],version:"v1.3.x",frontMatter:{}},i={},p=[{value:"Overview",id:"overview",level:2},{value:"Legend",id:"legend",level:2},{value:"Release Versioning",id:"release-versioning",level:2},{value:"Supported Releases",id:"supported-releases",level:2},{value:"Supported Kubernetes Versions",id:"supported-kubernetes-versions",level:2},{value:"Acknowledgement",id:"acknowledgement",level:2}],u={toc:p};function c(e){let{components:t,...r}=e;return(0,n.kt)("wrapper",(0,a.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("h1",{id:"release-management"},"Release Management"),(0,n.kt)("h2",{id:"overview"},"Overview"),(0,n.kt)("p",null,"This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades."),(0,n.kt)("h2",{id:"legend"},"Legend"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"X.Y.Z")," refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Breaking changes")," refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Milestone")," should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Patch releases")," refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility."),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("strong",{parentName:"li"},"Test gates")," should include soak tests and upgrade tests from the last minor version.")),(0,n.kt)("h2",{id:"release-versioning"},"Release Versioning"),(0,n.kt)("p",null,"All releases will be of the form ",(0,n.kt)("em",{parentName:"p"},"vX.Y.Z")," where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning."),(0,n.kt)("p",null,"The rest of the doc will cover the release process for the following kinds of releases:"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Major Releases")),(0,n.kt)("p",null,"No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Minor Releases")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"X.Y.0-alpha.W, W >= 0 (Branch : main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released as needed before we cut a beta X.Y release"),(0,n.kt)("li",{parentName:"ul"},"Alpha release, cut from master branch"))),(0,n.kt)("li",{parentName:"ul"},"X.Y.0-beta.W, W >= 0 (Branch : main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released as needed before we cut a stable X.Y release"),(0,n.kt)("li",{parentName:"ul"},"More stable than the alpha release to signal users to test things out"),(0,n.kt)("li",{parentName:"ul"},"Beta release, cut from master branch"))),(0,n.kt)("li",{parentName:"ul"},"X.Y.0-rc.W, W >= 0 (Branch : main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released as needed before we cut a stable X.Y release"),(0,n.kt)("li",{parentName:"ul"},"soak for ~ 2 weeks before cutting a stable release"),(0,n.kt)("li",{parentName:"ul"},"Release candidate release, cut from master branch"))),(0,n.kt)("li",{parentName:"ul"},"X.Y.0 (Branch: main)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"Released every ~ 3 months"),(0,n.kt)("li",{parentName:"ul"},"Stable release, cut from master when X.Y milestone is complete")))),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"Patch Releases")),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},"Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed)",(0,n.kt)("ul",{parentName:"li"},(0,n.kt)("li",{parentName:"ul"},"No breaking changes"),(0,n.kt)("li",{parentName:"ul"},"Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches."),(0,n.kt)("li",{parentName:"ul"},"Patch release, cut from a release-X.Y branch")))),(0,n.kt)("h2",{id:"supported-releases"},"Supported Releases"),(0,n.kt)("p",null,"Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed."),(0,n.kt)("p",null,"We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible."),(0,n.kt)("p",null,'We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.'),(0,n.kt)("h2",{id:"supported-kubernetes-versions"},"Supported Kubernetes Versions"),(0,n.kt)("p",null,"Eraser is assumed to be compatible with the ",(0,n.kt)("a",{parentName:"p",href:"https://kubernetes.io/releases/patch-releases/#detailed-release-history-for-active-branches"},"current Kubernetes Supported Versions")," per ",(0,n.kt)("a",{parentName:"p",href:"https://kubernetes.io/releases/version-skew-policy/"},"Kubernetes Supported Versions policy"),"."),(0,n.kt)("p",null,"For example, if Eraser ",(0,n.kt)("em",{parentName:"p"},"supported")," versions are v1.2 and v1.1, and Kubernetes ",(0,n.kt)("em",{parentName:"p"},"supported")," versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time."),(0,n.kt)("p",null,"If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk."),(0,n.kt)("h2",{id:"acknowledgement"},"Acknowledgement"),(0,n.kt)("p",null,"This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm."))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/ec0d5d9e.2c250436.js b/docs/assets/js/ec0d5d9e.2c250436.js deleted file mode 100644 index 7ba5dd1d73..0000000000 --- a/docs/assets/js/ec0d5d9e.2c250436.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1760],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>d});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=s(r),d=a,v=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function d(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var s=2;s<i;s++)o[s]=r[s];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},7125:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var n=r(7462),a=(r(7294),r(3905));const i={title:"Architecture"},o=void 0,l={unversionedId:"architecture",id:"version-v0.5.x/architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v0.5.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v0.5.x/architecture",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v0.5.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v0.5.x/manual-removal"}},c={},s=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}],u={toc:s};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"At a high level, Eraser has two main modes of operation: manual and automated."),(0,a.kt)("p",null,"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."),(0,a.kt)("p",null,"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."),(0,a.kt)("h2",{id:"manual-image-cleanup"},"Manual image cleanup"),(0,a.kt)("p",null,"Note: metrics are not yet implemented in Eraser v0.5.x, but will be available in the upcoming v1.0.0 release."),(0,a.kt)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),(0,a.kt)("h2",{id:"automated-analysis-scanning-and-cleanup"},"Automated analysis, scanning, and cleanup"),(0,a.kt)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"}))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/ec0d5d9e.3d394cb4.js b/docs/assets/js/ec0d5d9e.3d394cb4.js new file mode 100644 index 0000000000..128adeb46d --- /dev/null +++ b/docs/assets/js/ec0d5d9e.3d394cb4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1760],{5684:(e,a,n)=>{n.r(a),n.d(a,{assets:()=>o,contentTitle:()=>i,default:()=>d,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var t=n(5893),r=n(1151);const s={title:"Architecture"},i=void 0,l={id:"architecture",title:"Architecture",description:"At a high level, Eraser has two main modes of operation: manual and automated.",source:"@site/versioned_docs/version-v0.5.x/architecture.md",sourceDirName:".",slug:"/architecture",permalink:"/eraser/docs/v0.5.x/architecture",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Architecture"},sidebar:"sidebar",previous:{title:"Quick Start",permalink:"/eraser/docs/v0.5.x/quick-start"},next:{title:"Manual Removal",permalink:"/eraser/docs/v0.5.x/manual-removal"}},o={},c=[{value:"Manual image cleanup",id:"manual-image-cleanup",level:2},{value:"Automated analysis, scanning, and cleanup",id:"automated-analysis-scanning-and-cleanup",level:2}];function u(e){const a={h2:"h2",p:"p",...(0,r.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(a.p,{children:"At a high level, Eraser has two main modes of operation: manual and automated."}),"\n",(0,t.jsx)(a.p,{children:"Manual image removal involves supplying a list of images to remove; Eraser then\ndeploys pods to clean up the images you supplied."}),"\n",(0,t.jsx)(a.p,{children:"Automated image removal runs on a timer. By default, the automated process\nremoves images based on the results of a vulnerability scan. The default\nvulnerability scanner is Trivy, but others can be provided in its place. Or,\nthe scanner can be disabled altogether, in which case Eraser acts as a garbage\ncollector -- it will remove all non-running images in your cluster."}),"\n",(0,t.jsx)(a.h2,{id:"manual-image-cleanup",children:"Manual image cleanup"}),"\n",(0,t.jsx)(a.p,{children:"Note: metrics are not yet implemented in Eraser v0.5.x, but will be available in the upcoming v1.0.0 release."}),"\n",(0,t.jsx)("img",{title:"manual cleanup",src:"/eraser/docs/img/eraser_manual.png"}),"\n",(0,t.jsx)(a.h2,{id:"automated-analysis-scanning-and-cleanup",children:"Automated analysis, scanning, and cleanup"}),"\n",(0,t.jsx)("img",{title:"automated cleanup",src:"/eraser/docs/img/eraser_timer.png"})]})}function d(e={}){const{wrapper:a}={...(0,r.a)(),...e.components};return a?(0,t.jsx)(a,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},1151:(e,a,n)=>{n.d(a,{Z:()=>l,a:()=>i});var t=n(7294);const r={},s=t.createContext(r);function i(e){const a=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(a):{...a,...e}}),[a,e])}function l(e){let a;return a=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),t.createElement(s.Provider,{value:a},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ed8448fe.485bf575.js b/docs/assets/js/ed8448fe.485bf575.js new file mode 100644 index 0000000000..c41e77a05c --- /dev/null +++ b/docs/assets/js/ed8448fe.485bf575.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1857],{859:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var r=s(5893),a=s(1151);const t={title:"Manual Removal"},i=void 0,l={id:"manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.2.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v1.2.x/manual-removal",draft:!1,unlisted:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v1.2.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v1.2.x/exclusion"}},o={},c=[];function d(e){const n={blockquote:"blockquote",code:"code",p:"p",pre:"pre",...(0,a.a)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Create an ",(0,r.jsx)(n.code,{children:"ImageList"})," and specify the images you would like to remove. In this case, the image ",(0,r.jsx)(n.code,{children:"docker.io/library/alpine:3.7.3"})," will be removed."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n'})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"ImageList"})," is a cluster-scoped resource and must be called imagelist. ",(0,r.jsx)(n.code,{children:'"*"'})," can be specified to remove all non-running images instead of individual images."]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["Creating an ",(0,r.jsx)(n.code,{children:"ImageList"})," should trigger an ",(0,r.jsx)(n.code,{children:"ImageJob"})," that will deploy Eraser pods on every node to perform the removal given the list of images."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n"})}),"\n",(0,r.jsx)(n.p,{children:"Pods will run to completion and the images will be removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"ImageList"})," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n"})}),"\n",(0,r.jsx)(n.p,{children:"Verify the unused images are removed."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n"})}),"\n",(0,r.jsx)(n.p,{children:"If the image has been successfully removed, there will be no output."})]})}function m(e={}){const{wrapper:n}={...(0,a.a)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},1151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>i});var r=s(7294);const a={},t=r.createContext(a);function i(e){const n=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ed8448fe.b3589d7f.js b/docs/assets/js/ed8448fe.b3589d7f.js deleted file mode 100644 index 24a2b09429..0000000000 --- a/docs/assets/js/ed8448fe.b3589d7f.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1857],{3905:(e,n,r)=>{r.d(n,{Zo:()=>m,kt:()=>d});var t=r(7294);function a(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function l(e,n){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),r.push.apply(r,t)}return r}function o(e){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?l(Object(r),!0).forEach((function(n){a(e,n,r[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):l(Object(r)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))}))}return e}function s(e,n){if(null==e)return{};var r,t,a=function(e,n){if(null==e)return{};var r,t,a={},l=Object.keys(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||(a[r]=e[r]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(t=0;t<l.length;t++)r=l[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var i=t.createContext({}),c=function(e){var n=t.useContext(i),r=n;return e&&(r="function"==typeof e?e(n):o(o({},n),e)),r},m=function(e){var n=c(e.components);return t.createElement(i.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},u=t.forwardRef((function(e,n){var r=e.components,a=e.mdxType,l=e.originalType,i=e.parentName,m=s(e,["components","mdxType","originalType","parentName"]),u=c(r),d=a,g=u["".concat(i,".").concat(d)]||u[d]||p[d]||l;return r?t.createElement(g,o(o({ref:n},m),{},{components:r})):t.createElement(g,o({ref:n},m))}));function d(e,n){var r=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var l=r.length,o=new Array(l);o[0]=u;var s={};for(var i in n)hasOwnProperty.call(n,i)&&(s[i]=n[i]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var c=2;c<l;c++)o[c]=r[c];return t.createElement.apply(null,o)}return t.createElement.apply(null,r)}u.displayName="MDXCreateElement"},4552:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>o,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});var t=r(7462),a=(r(7294),r(3905));const l={title:"Manual Removal"},o=void 0,s={unversionedId:"manual-removal",id:"version-v1.2.x/manual-removal",title:"Manual Removal",description:"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.",source:"@site/versioned_docs/version-v1.2.x/manual-removal.md",sourceDirName:".",slug:"/manual-removal",permalink:"/eraser/docs/v1.2.x/manual-removal",draft:!1,tags:[],version:"v1.2.x",frontMatter:{title:"Manual Removal"},sidebar:"sidebar",previous:{title:"Architecture",permalink:"/eraser/docs/v1.2.x/architecture"},next:{title:"Exclusion",permalink:"/eraser/docs/v1.2.x/exclusion"}},i={},c=[],m={toc:c};function p(e){let{components:n,...r}=e;return(0,a.kt)("wrapper",(0,t.Z)({},m,r,{components:n,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"Create an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," and specify the images you would like to remove. In this case, the image ",(0,a.kt)("inlineCode",{parentName:"p"},"docker.io/library/alpine:3.7.3")," will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},'cat <<EOF | kubectl apply -f -\napiVersion: eraser.sh/v1alpha1\nkind: ImageList\nmetadata:\n name: imagelist\nspec:\n images:\n - docker.io/library/alpine:3.7.3 # use "*" for all non-running images\nEOF\n')),(0,a.kt)("blockquote",null,(0,a.kt)("p",{parentName:"blockquote"},(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," is a cluster-scoped resource and must be called imagelist. ",(0,a.kt)("inlineCode",{parentName:"p"},'"*"')," can be specified to remove all non-running images instead of individual images.")),(0,a.kt)("p",null,"Creating an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," should trigger an ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageJob")," that will deploy Eraser pods on every node to perform the removal given the list of images."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s\neraser-system eraser-kind-control-plane 1/1 Running 0 11s\neraser-system eraser-kind-worker 1/1 Running 0 11s\neraser-system eraser-kind-worker2 1/1 Running 0 11s\n")),(0,a.kt)("p",null,"Pods will run to completion and the images will be removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl get pods -n eraser-system\neraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s\neraser-system eraser-kind-control-plane 0/1 Completed 0 22s\neraser-system eraser-kind-worker 0/1 Completed 0 22s\neraser-system eraser-kind-worker2 0/1 Completed 0 22s\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"ImageList")," custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ kubectl describe ImageList imagelist\n...\nStatus:\n Failed: 0\n Success: 3\n Timestamp: 2022-02-25T23:41:55Z\n...\n")),(0,a.kt)("p",null,"Verify the unused images are removed."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-shell"},"$ docker exec kind-worker ctr -n k8s.io images list | grep alpine\n")),(0,a.kt)("p",null,"If the image has been successfully removed, there will be no output."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/efdb11b6.0bcb2915.js b/docs/assets/js/efdb11b6.0bcb2915.js new file mode 100644 index 0000000000..94bd536cbb --- /dev/null +++ b/docs/assets/js/efdb11b6.0bcb2915.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4111],{7064:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v0.5.x","label":"v0.5.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v0.5.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v0.5.x/","docId":"introduction","unlisted":false},{"type":"link","label":"Installation","href":"/eraser/docs/v0.5.x/installation","docId":"installation","unlisted":false},{"type":"link","label":"Quick Start","href":"/eraser/docs/v0.5.x/quick-start","docId":"quick-start","unlisted":false},{"type":"link","label":"Architecture","href":"/eraser/docs/v0.5.x/architecture","docId":"architecture","unlisted":false},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v0.5.x/manual-removal","docId":"manual-removal","unlisted":false},{"type":"link","label":"Exclusion","href":"/eraser/docs/v0.5.x/exclusion","docId":"exclusion","unlisted":false},{"type":"link","label":"Customization","href":"/eraser/docs/v0.5.x/customization","docId":"customization","unlisted":false}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v0.5.x/setup","docId":"setup","unlisted":false},{"type":"link","label":"Releasing","href":"/eraser/docs/v0.5.x/releasing","docId":"releasing","unlisted":false}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v0.5.x/custom-scanner","docId":"custom-scanner","unlisted":false},{"type":"link","label":"Trivy","href":"/eraser/docs/v0.5.x/trivy","docId":"trivy","unlisted":false}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v0.5.x/faq","docId":"faq","unlisted":false},{"type":"link","label":"Contributing","href":"/eraser/docs/v0.5.x/contributing","docId":"contributing","unlisted":false},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v0.5.x/code-of-conduct","docId":"code-of-conduct","unlisted":false}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Overview","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/efdb11b6.c5386572.js b/docs/assets/js/efdb11b6.c5386572.js deleted file mode 100644 index fbea518dbc..0000000000 --- a/docs/assets/js/efdb11b6.c5386572.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4111],{7064:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"v0.5.x","label":"v0.5.x","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-v0.5.x","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/eraser/docs/v0.5.x/","docId":"introduction"},{"type":"link","label":"Installation","href":"/eraser/docs/v0.5.x/installation","docId":"installation"},{"type":"link","label":"Quick Start","href":"/eraser/docs/v0.5.x/quick-start","docId":"quick-start"},{"type":"link","label":"Architecture","href":"/eraser/docs/v0.5.x/architecture","docId":"architecture"},{"type":"category","label":"Topics","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Manual Removal","href":"/eraser/docs/v0.5.x/manual-removal","docId":"manual-removal"},{"type":"link","label":"Exclusion","href":"/eraser/docs/v0.5.x/exclusion","docId":"exclusion"},{"type":"link","label":"Customization","href":"/eraser/docs/v0.5.x/customization","docId":"customization"}]},{"type":"category","label":"Development","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Setup","href":"/eraser/docs/v0.5.x/setup","docId":"setup"},{"type":"link","label":"Releasing","href":"/eraser/docs/v0.5.x/releasing","docId":"releasing"}]},{"type":"category","label":"Scanning","collapsible":true,"collapsed":false,"items":[{"type":"link","label":"Custom Scanner","href":"/eraser/docs/v0.5.x/custom-scanner","docId":"custom-scanner"},{"type":"link","label":"Trivy","href":"/eraser/docs/v0.5.x/trivy","docId":"trivy"}]},{"type":"link","label":"FAQ","href":"/eraser/docs/v0.5.x/faq","docId":"faq"},{"type":"link","label":"Contributing","href":"/eraser/docs/v0.5.x/contributing","docId":"contributing"},{"type":"link","label":"Code of Conduct","href":"/eraser/docs/v0.5.x/code-of-conduct","docId":"code-of-conduct"}]},"docs":{"architecture":{"id":"architecture","title":"Architecture","description":"At a high level, Eraser has two main modes of operation: manual and automated.","sidebar":"sidebar"},"code-of-conduct":{"id":"code-of-conduct","title":"Code of Conduct","description":"This project has adopted the CNCF Code of Conduct.","sidebar":"sidebar"},"contributing":{"id":"contributing","title":"Contributing","description":"There are several ways to get involved with Eraser","sidebar":"sidebar"},"custom-scanner":{"id":"custom-scanner","title":"Custom Scanner","description":"Creating a Custom Scanner","sidebar":"sidebar"},"customization":{"id":"customization","title":"Customization","description":"By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:","sidebar":"sidebar"},"exclusion":{"id":"exclusion","title":"Exclusion","description":"Excluding registries, repositories, and images","sidebar":"sidebar"},"faq":{"id":"faq","title":"FAQ","description":"Why am I still seeing vulnerable images?","sidebar":"sidebar"},"installation":{"id":"installation","title":"Installation","description":"Manifest","sidebar":"sidebar"},"introduction":{"id":"introduction","title":"Introduction","description":"When deploying to Kubernetes, it\'s common for pipelines to build and push images to a cluster, but it\'s much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.","sidebar":"sidebar"},"manual-removal":{"id":"manual-removal","title":"Manual Removal","description":"Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.","sidebar":"sidebar"},"quick-start":{"id":"quick-start","title":"Quick Start","description":"This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.","sidebar":"sidebar"},"releasing":{"id":"releasing","title":"Releasing","description":"Overview","sidebar":"sidebar"},"setup":{"id":"setup","title":"Setup","description":"This document describes the steps to get started with development.","sidebar":"sidebar"},"trivy":{"id":"trivy","title":"Trivy","description":"Trivy Provider Options","sidebar":"sidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/f2ef54d0.06e099a0.js b/docs/assets/js/f2ef54d0.06e099a0.js new file mode 100644 index 0000000000..4e7f125181 --- /dev/null +++ b/docs/assets/js/f2ef54d0.06e099a0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6039],{9081:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var i=t(5893),r=t(1151);const a={title:"FAQ"},s=void 0,o={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.1.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v1.1.x/faq",draft:!1,unlisted:!1,tags:[],version:"v1.1.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v1.1.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v1.1.x/contributing"}},l={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}];function u(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,i.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"configmap"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"how-is-eraser-different-from-kubernetes-garbage-collection",children:"How is Eraser different from Kubernetes garbage collection?"}),"\n",(0,i.jsxs)(n.p,{children:["The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/",children:"Kubernetes documentation"}),", and configuration options can be found in the ",(0,i.jsx)(n.a,{href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/",children:"Kubelet documentation"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"There are a couple core benefits to using Eraser for image cleanup:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Eraser can be configured to use image vulnerability data when making determinations on image removal"}),"\n",(0,i.jsx)(n.li,{children:"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes"}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>o,a:()=>s});var i=t(7294);const r={},a=i.createContext(r);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/f2ef54d0.4af2136b.js b/docs/assets/js/f2ef54d0.4af2136b.js deleted file mode 100644 index 2893782971..0000000000 --- a/docs/assets/js/f2ef54d0.4af2136b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6039],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?i(Object(r),!0).forEach((function(t){a(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):i(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,a=function(e,t){if(null==e)return{};var r,n,a={},i=Object.keys(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),f=c(r),b=a,g=f["".concat(s,".").concat(b)]||f[b]||p[b]||i;return r?n.createElement(g,o(o({ref:t},u),{},{components:r})):n.createElement(g,o({ref:t},u))}));function b(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=r.length,o=new Array(i);o[0]=f;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c<i;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}f.displayName="MDXCreateElement"},6782:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(7462),a=(r(7294),r(3905));const i={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"version-v1.1.x/faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v1.1.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v1.1.x/faq",draft:!1,tags:[],version:"v1.1.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v1.1.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v1.1.x/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2},{value:"How is Eraser different from Kubernetes garbage collection?",id:"how-is-eraser-different-from-kubernetes-garbage-collection",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,a.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,a.kt)("p",null,"Eraser currently targets ",(0,a.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,a.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the ",(0,a.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"configmap"),"."),(0,a.kt)("h2",{id:"how-is-eraser-different-from-kubernetes-garbage-collection"},"How is Eraser different from Kubernetes garbage collection?"),(0,a.kt)("p",null,"The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/concepts/architecture/garbage-collection/"},"Kubernetes documentation"),", and configuration options can be found in the ",(0,a.kt)("a",{parentName:"p",href:"https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/"},"Kubelet documentation"),". "),(0,a.kt)("p",null,"There are a couple core benefits to using Eraser for image cleanup:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Eraser can be configured to use image vulnerability data when making determinations on image removal"),(0,a.kt)("li",{parentName:"ul"},"By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/fa2b770f.4d309065.js b/docs/assets/js/fa2b770f.4d309065.js deleted file mode 100644 index 8da7da6588..0000000000 --- a/docs/assets/js/fa2b770f.4d309065.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6148],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function o(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)r=a[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):o(o({},t),e)),r},u=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),m=c(r),f=i,v=m["".concat(s,".").concat(f)]||m[f]||p[f]||a;return r?n.createElement(v,o(o({ref:t},u),{},{components:r})):n.createElement(v,o({ref:t},u))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,o=new Array(a);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var c=2;c<a;c++)o[c]=r[c];return n.createElement.apply(null,o)}return n.createElement.apply(null,r)}m.displayName="MDXCreateElement"},9974:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const a={title:"FAQ"},o=void 0,l={unversionedId:"faq",id:"version-v0.5.x/faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v0.5.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v0.5.x/faq",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v0.5.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v0.5.x/contributing"}},s={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2}],u={toc:c};function p(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"why-am-i-still-seeing-vulnerable-images"},"Why am I still seeing vulnerable images?"),(0,i.kt)("p",null,"Eraser currently targets ",(0,i.kt)("strong",{parentName:"p"},"non-running")," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.kt)("inlineCode",{parentName:"p"},"CRITICAL")," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the ",(0,i.kt)("inlineCode",{parentName:"p"},"--severity")," flag."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/fa2b770f.f4f734aa.js b/docs/assets/js/fa2b770f.f4f734aa.js new file mode 100644 index 0000000000..d87c5d2d29 --- /dev/null +++ b/docs/assets/js/fa2b770f.f4f734aa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6148],{496:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>d,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var i=t(5893),r=t(1151);const s={title:"FAQ"},a=void 0,l={id:"faq",title:"FAQ",description:"Why am I still seeing vulnerable images?",source:"@site/versioned_docs/version-v0.5.x/faq.md",sourceDirName:".",slug:"/faq",permalink:"/eraser/docs/v0.5.x/faq",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"FAQ"},sidebar:"sidebar",previous:{title:"Trivy",permalink:"/eraser/docs/v0.5.x/trivy"},next:{title:"Contributing",permalink:"/eraser/docs/v0.5.x/contributing"}},o={},c=[{value:"Why am I still seeing vulnerable images?",id:"why-am-i-still-seeing-vulnerable-images",level:2}];function u(e){const n={code:"code",h2:"h2",p:"p",strong:"strong",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"why-am-i-still-seeing-vulnerable-images",children:"Why am I still seeing vulnerable images?"}),"\n",(0,i.jsxs)(n.p,{children:["Eraser currently targets ",(0,i.jsx)(n.strong,{children:"non-running"})," images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with ",(0,i.jsx)(n.code,{children:"CRITICAL"})," vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the ",(0,i.jsx)(n.code,{children:"--severity"})," flag."]})]})}function d(e={}){const{wrapper:n}={...(0,r.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},1151:(e,n,t)=>{t.d(n,{Z:()=>l,a:()=>a});var i=t(7294);const r={},s=i.createContext(r);function a(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/faa9d310.5838e10c.js b/docs/assets/js/faa9d310.5838e10c.js new file mode 100644 index 0000000000..7d26637f87 --- /dev/null +++ b/docs/assets/js/faa9d310.5838e10c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6578],{2492:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var i=n(5893),r=n(1151);const s={title:"Trivy"},o=void 0,l={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v0.4.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v0.4.x/trivy",draft:!1,unlisted:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v0.4.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v0.4.x/faq"}},a={},c=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function d(e){const t={h2:"h2",li:"li",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,i.jsx)(t.p,{children:"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"--ignore-unfixed: boolean to report only fixed vulnerabilities (default true)"}),"\n",(0,i.jsx)(t.li,{children:'--security-checks: comma-separated list of what security issues to detect (default "vuln")'}),"\n",(0,i.jsx)(t.li,{children:'--vuln-type: list of severity levels to report (default "CRITICAL")'}),"\n",(0,i.jsx)(t.li,{children:"--delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)"}),"\n"]})]})}function u(e={}){const{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1151:(e,t,n)=>{n.d(t,{Z:()=>l,a:()=>o});var i=n(7294);const r={},s=i.createContext(r);function o(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/faa9d310.9de6aa31.js b/docs/assets/js/faa9d310.9de6aa31.js deleted file mode 100644 index a20aa99d92..0000000000 --- a/docs/assets/js/faa9d310.9de6aa31.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6578],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?o(Object(r),!0).forEach((function(t){i(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):o(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function l(e,t){if(null==e)return{};var r,n,i=function(e,t){if(null==e)return{};var r,n,i={},o=Object.keys(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n<o.length;n++)r=o[n],t.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},v=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,o=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),v=c(r),f=i,d=v["".concat(s,".").concat(f)]||v[f]||u[f]||o;return r?n.createElement(d,a(a({ref:t},p),{},{components:r})):n.createElement(d,a({ref:t},p))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var o=r.length,a=new Array(o);a[0]=v;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,a[1]=l;for(var c=2;c<o;c++)a[c]=r[c];return n.createElement.apply(null,a)}return n.createElement.apply(null,r)}v.displayName="MDXCreateElement"},5354:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var n=r(7462),i=(r(7294),r(3905));const o={title:"Trivy"},a=void 0,l={unversionedId:"trivy",id:"version-v0.4.x/trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/versioned_docs/version-v0.4.x/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/v0.4.x/trivy",draft:!1,tags:[],version:"v0.4.x",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/v0.4.x/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/v0.4.x/faq"}},s={},c=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],p={toc:c};function u(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,i.kt)("p",null,"The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"--ignore-unfixed: boolean to report only fixed vulnerabilities (default true)"),(0,i.kt)("li",{parentName:"ul"},'--security-checks: comma-separated list of what security issues to detect (default "vuln")'),(0,i.kt)("li",{parentName:"ul"},'--vuln-type: list of severity levels to report (default "CRITICAL")'),(0,i.kt)("li",{parentName:"ul"},"--delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/fc618254.c686b75c.js b/docs/assets/js/fc618254.c686b75c.js deleted file mode 100644 index ca2fa2ae27..0000000000 --- a/docs/assets/js/fc618254.c686b75c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4428],{3905:(e,r,t)=>{t.d(r,{Zo:()=>c,kt:()=>m});var n=t(7294);function i(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?a(Object(t),!0).forEach((function(r){i(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):a(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function o(e,r){if(null==e)return{};var t,n,i=function(e,r){if(null==e)return{};var t,n,i={},a=Object.keys(e);for(n=0;n<a.length;n++)t=a[n],r.indexOf(t)>=0||(i[t]=e[t]);return i}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n<a.length;n++)t=a[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},c=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},d={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},u=n.forwardRef((function(e,r){var t=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),u=p(t),m=i,f=u["".concat(s,".").concat(m)]||u[m]||d[m]||a;return t?n.createElement(f,l(l({ref:r},c),{},{components:t})):n.createElement(f,l({ref:r},c))}));function m(e,r){var t=arguments,i=r&&r.mdxType;if("string"==typeof e||i){var a=t.length,l=new Array(a);l[0]=u;var o={};for(var s in r)hasOwnProperty.call(r,s)&&(o[s]=r[s]);o.originalType=e,o.mdxType="string"==typeof e?e:i,l[1]=o;for(var p=2;p<a;p++)l[p]=t[p];return n.createElement.apply(null,l)}return n.createElement.apply(null,t)}u.displayName="MDXCreateElement"},5055:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>a,metadata:()=>o,toc:()=>p});var n=t(7462),i=(t(7294),t(3905));const a={title:"Exclusion"},l=void 0,o={unversionedId:"exclusion",id:"version-v0.5.x/exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v0.5.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v0.5.x/exclusion",draft:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v0.5.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v0.5.x/customization"}},s={},p=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}],c={toc:p};function d(e){let{components:r,...t}=e;return(0,i.kt)("wrapper",(0,n.Z)({},c,t,{components:r,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"excluding-registries-repositories-and-images"},"Excluding registries, repositories, and images"),(0,i.kt)("p",null,"Eraser can exclude registries (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/*"),") and also specific images with a tag (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"docker.io/library/ubuntu:18.04"),") or digest (example, ",(0,i.kt)("inlineCode",{parentName:"p"},"sha256:80f31da1ac7b312ba29d65080fd..."),") from its removal process."),(0,i.kt)("p",null,"To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/exclude.list=true")," in the eraser-system namespace with a JSON file holding the excluded images."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},'$ cat > sample.json <<EOF\n{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n')),(0,i.kt)("h2",{id:"exempting-nodes-from-the-eraser-pipeline"},"Exempting Nodes from the Eraser Pipeline"),(0,i.kt)("p",null,"Exempting nodes with ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes")," is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.kt)("inlineCode",{parentName:"p"},"include")," or ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude")," from the cleanup process using the ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes")," argument. "),(0,i.kt)("p",null,(0,i.kt)("em",{parentName:"p"},"See ",(0,i.kt)("a",{parentName:"em",href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md"},"Eraser Helm Chart")," for more information on deployment.")),(0,i.kt)("p",null,"Nodes with the selector ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter")," will be filtered accordingly. "),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"If ",(0,i.kt)("inlineCode",{parentName:"li"},"include")," is provided, eraser and collector pods will only be scheduled on nodes with the selector ",(0,i.kt)("inlineCode",{parentName:"li"},"eraser.sh/cleanup.filter"),". "),(0,i.kt)("li",{parentName:"ul"},"If ",(0,i.kt)("inlineCode",{parentName:"li"},"exclude")," is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector ",(0,i.kt)("inlineCode",{parentName:"li"},"eraser.sh/cleanup.filter"),".")),(0,i.kt)("p",null,"Unless specified, the default value of ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes")," is ",(0,i.kt)("inlineCode",{parentName:"p"},"exclude"),". Because Windows nodes are not supported, they will always be excluded regardless of the ",(0,i.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter")," label or the value of ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes"),"."),(0,i.kt)("p",null,"Additional node selectors can be provided through the ",(0,i.kt)("inlineCode",{parentName:"p"},"--filter-nodes-selector")," flag."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/fc618254.e65d5a68.js b/docs/assets/js/fc618254.e65d5a68.js new file mode 100644 index 0000000000..ff6b6d5134 --- /dev/null +++ b/docs/assets/js/fc618254.e65d5a68.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4428],{2646:(e,s,r)=>{r.r(s),r.d(s,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>t,toc:()=>c});var i=r(5893),n=r(1151);const l={title:"Exclusion"},o=void 0,t={id:"exclusion",title:"Exclusion",description:"Excluding registries, repositories, and images",source:"@site/versioned_docs/version-v0.5.x/exclusion.md",sourceDirName:".",slug:"/exclusion",permalink:"/eraser/docs/v0.5.x/exclusion",draft:!1,unlisted:!1,tags:[],version:"v0.5.x",frontMatter:{title:"Exclusion"},sidebar:"sidebar",previous:{title:"Manual Removal",permalink:"/eraser/docs/v0.5.x/manual-removal"},next:{title:"Customization",permalink:"/eraser/docs/v0.5.x/customization"}},d={},c=[{value:"Excluding registries, repositories, and images",id:"excluding-registries-repositories-and-images",level:2},{value:"Exempting Nodes from the Eraser Pipeline",id:"exempting-nodes-from-the-eraser-pipeline",level:2}];function a(e){const s={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,n.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.h2,{id:"excluding-registries-repositories-and-images",children:"Excluding registries, repositories, and images"}),"\n",(0,i.jsxs)(s.p,{children:["Eraser can exclude registries (example, ",(0,i.jsx)(s.code,{children:"docker.io/library/*"}),") and also specific images with a tag (example, ",(0,i.jsx)(s.code,{children:"docker.io/library/ubuntu:18.04"}),") or digest (example, ",(0,i.jsx)(s.code,{children:"sha256:80f31da1ac7b312ba29d65080fd..."}),") from its removal process."]}),"\n",(0,i.jsxs)(s.p,{children:["To exclude any images or registries from the removal, create configmap(s) with the label ",(0,i.jsx)(s.code,{children:"eraser.sh/exclude.list=true"})," in the eraser-system namespace with a JSON file holding the excluded images."]}),"\n",(0,i.jsx)(s.pre,{children:(0,i.jsx)(s.code,{className:"language-bash",children:'$ cat > sample.json <<EOF\n{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}\nEOF\n\n$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system\n$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system\n'})}),"\n",(0,i.jsx)(s.h2,{id:"exempting-nodes-from-the-eraser-pipeline",children:"Exempting Nodes from the Eraser Pipeline"}),"\n",(0,i.jsxs)(s.p,{children:["Exempting nodes with ",(0,i.jsx)(s.code,{children:"--filter-nodes"})," is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to ",(0,i.jsx)(s.code,{children:"include"})," or ",(0,i.jsx)(s.code,{children:"exclude"})," from the cleanup process using the ",(0,i.jsx)(s.code,{children:"--filter-nodes"})," argument."]}),"\n",(0,i.jsx)(s.p,{children:(0,i.jsxs)(s.em,{children:["See ",(0,i.jsx)(s.a,{href:"https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md",children:"Eraser Helm Chart"})," for more information on deployment."]})}),"\n",(0,i.jsxs)(s.p,{children:["Nodes with the selector ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"})," will be filtered accordingly."]}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsxs)(s.li,{children:["If ",(0,i.jsx)(s.code,{children:"include"})," is provided, eraser and collector pods will only be scheduled on nodes with the selector ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"}),"."]}),"\n",(0,i.jsxs)(s.li,{children:["If ",(0,i.jsx)(s.code,{children:"exclude"})," is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"}),"."]}),"\n"]}),"\n",(0,i.jsxs)(s.p,{children:["Unless specified, the default value of ",(0,i.jsx)(s.code,{children:"--filter-nodes"})," is ",(0,i.jsx)(s.code,{children:"exclude"}),". Because Windows nodes are not supported, they will always be excluded regardless of the ",(0,i.jsx)(s.code,{children:"eraser.sh/cleanup.filter"})," label or the value of ",(0,i.jsx)(s.code,{children:"--filter-nodes"}),"."]}),"\n",(0,i.jsxs)(s.p,{children:["Additional node selectors can be provided through the ",(0,i.jsx)(s.code,{children:"--filter-nodes-selector"})," flag."]})]})}function h(e={}){const{wrapper:s}={...(0,n.a)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},1151:(e,s,r)=>{r.d(s,{Z:()=>t,a:()=>o});var i=r(7294);const n={},l=i.createContext(n);function o(e){const s=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function t(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),i.createElement(l.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/fcff9033.00614336.js b/docs/assets/js/fcff9033.00614336.js new file mode 100644 index 0000000000..1aed88d523 --- /dev/null +++ b/docs/assets/js/fcff9033.00614336.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4497],{6979:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var t=r(5893),s=r(1151);const o={title:"Customization"},i=void 0,a={id:"customization",title:"Customization",description:"Overview",source:"@site/docs/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/next/customization",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/next/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/next/metrics"}},c={},l=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}];function d(e){const n={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.a)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsx)(n.p,{children:"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"kubectl edit configmap --namespace eraser-system eraser-manager-config\n"})}),"\n",(0,t.jsx)(n.p,{children:"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."}),"\n",(0,t.jsx)(n.h2,{id:"key-concepts",children:"Key Concepts"}),"\n",(0,t.jsx)(n.h3,{id:"basic-architecture",children:"Basic architecture"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.em,{children:"manager"})," runs as a pod in your cluster and manages ",(0,t.jsx)(n.em,{children:"ImageJobs"}),". Think of\nan ",(0,t.jsx)(n.em,{children:"ImageJob"})," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,t.jsx)(n.em,{children:"ImageJob"})," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Assessment"}),"\n",(0,t.jsx)(n.li,{children:"Removal."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"scheduling",children:"Scheduling"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," can either be created on-demand (see ",(0,t.jsx)(n.a,{href:"https://eraser-dev.github.io/eraser/docs/manual-removal",children:"Manual Removal"}),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."]}),"\n",(0,t.jsx)(n.h3,{id:"fault-tolerance",children:"Fault Tolerance"}),"\n",(0,t.jsxs)(n.p,{children:["Because an ",(0,t.jsx)(n.em,{children:"ImageJob"})," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,t.jsx)(n.code,{children:"manager.imageJob.successRatio"})," property to\n",(0,t.jsx)(n.code,{children:"1.0"}),". If 75% success sounds good to you, set it to ",(0,t.jsx)(n.code,{children:"0.75"}),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,t.jsx)(n.em,{children:"ImageJob"})," report success, the job as\na whole will be marked as a failure."]}),"\n",(0,t.jsxs)(n.p,{children:["This is mainly to help diagnose error conditions. As such, you can set\n",(0,t.jsx)(n.code,{children:"manager.imageJob.cleanup.delayOnFailure"})," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."]}),"\n",(0,t.jsx)(n.h3,{id:"excluding-nodes",children:"Excluding Nodes"}),"\n",(0,t.jsxs)(n.p,{children:["For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,t.jsx)(n.code,{children:"eraser.sh/cleanup.filter"}),", but you can configure the behavior with\nthe options under ",(0,t.jsx)(n.code,{children:"manager.nodeFilter"}),". The ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"})," provides more detail."]}),"\n",(0,t.jsx)(n.h3,{id:"configuring-components",children:"Configuring Components"}),"\n",(0,t.jsxs)(n.p,{children:["An ",(0,t.jsx)(n.em,{children:"ImageJob"})," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Collection (What is on the node?)"}),"\n",(0,t.jsx)(n.li,{children:"Scanning (What images conform to the policy I've provided?)"}),"\n",(0,t.jsx)(n.li,{children:"Removal (Remove images based on the results of the above)"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,t.jsx)(n.em,{children:"ImageJobs"})," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["The collector and/or scanner ",(0,t.jsx)(n.code,{children:"components"})," are enabled, AND"]}),"\n",(0,t.jsxs)(n.li,{children:["The job was ",(0,t.jsx)(n.em,{children:"not"})," triggered manually by creating an ",(0,t.jsx)(n.em,{children:"ImageList"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"swapping-out-components",children:"Swapping out components"}),"\n",(0,t.jsxs)(n.p,{children:["The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,t.jsx)(n.code,{children:"components.<component>.image.repo"})," and ",(0,t.jsx)(n.code,{children:"components.<component>.image.tag"}),",\nwhere ",(0,t.jsx)(n.code,{children:"<component>"})," is one of ",(0,t.jsx)(n.code,{children:"collector"}),", ",(0,t.jsx)(n.code,{children:"scanner"}),", or ",(0,t.jsx)(n.code,{children:"remover"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"universal-options",children:"Universal Options"}),"\n",(0,t.jsxs)(n.p,{children:["The following portions of the configmap apply no matter how you spawn your\n",(0,t.jsx)(n.em,{children:"ImageJob"}),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,t.jsx)(n.a,{href:"#detailed-options",children:"table"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'manager:\n runtime:\n name: containerd\n address: unix:///run/containerd/containerd.sock\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n'})}),"\n",(0,t.jsx)(n.h2,{id:"component-options",children:"Component Options"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n"})}),"\n",(0,t.jsx)(n.h2,{id:"scanner-options",children:"Scanner Options"}),"\n",(0,t.jsxs)(n.p,{children:["These options can be provided to ",(0,t.jsx)(n.code,{children:"components.scanner.config"}),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."]}),"\n",(0,t.jsxs)(n.p,{children:["Below are the values recognized by the provided ",(0,t.jsx)(n.code,{children:"eraser-trivy-scanner"})," image.\nValues provided below are the defaults."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more information\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\n ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n"})}),"\n",(0,t.jsx)(n.h2,{id:"detailed-options",children:"Detailed Options"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Option"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Default"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.runtime.name"}),(0,t.jsx)(n.td,{children:"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."}),(0,t.jsx)(n.td,{children:"containerd"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.runtime.address"}),(0,t.jsx)(n.td,{children:"The runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions."}),(0,t.jsx)(n.td,{children:"unix:///run/containerd/containerd.sock"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.otlpEndpoint"}),(0,t.jsx)(n.td,{children:"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.logLevel"}),(0,t.jsx)(n.td,{children:"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."}),(0,t.jsx)(n.td,{children:"info"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.repeatInterval"}),(0,t.jsxs)(n.td,{children:["Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,t.jsx)(n.em,{children:"ImageJob"})," at the interval provided."]}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.scheduling.beginImmediately"}),(0,t.jsxs)(n.td,{children:["If set to true, the fist ",(0,t.jsx)(n.em,{children:"ImageJob"})," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."]}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.enabled"}),(0,t.jsxs)(n.td,{children:["Whether to enable profiling for the manager's containers. This is for debugging with ",(0,t.jsx)(n.code,{children:"go tool pprof"}),"."]}),(0,t.jsx)(n.td,{children:"false"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.profile.port"}),(0,t.jsx)(n.td,{children:"The port on which to expose the profiling endpoint."}),(0,t.jsx)(n.td,{children:"6060"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.successRatio"}),(0,t.jsx)(n.td,{children:"The ratio of successful image jobs required before a cleanup is performed."}),(0,t.jsx)(n.td,{children:"1.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnSuccess"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a successful image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"0s"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.imageJob.cleanup.delayOnFailure"}),(0,t.jsx)(n.td,{children:"The amount of time to wait after a failed image job before performing cleanup."}),(0,t.jsx)(n.td,{children:"24h"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.pullSecrets"}),(0,t.jsx)(n.td,{children:"The image pull secrets to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.priorityClassName"}),(0,t.jsx)(n.td,{children:"The priority class to use for collector, scanner, and remover containers."}),(0,t.jsx)(n.td,{children:'""'})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.type"}),(0,t.jsx)(n.td,{children:'The type of node filter to use. Must be either "exclude" or "include".'}),(0,t.jsx)(n.td,{children:"exclude"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"manager.nodeFilter.selectors"}),(0,t.jsx)(n.td,{children:"A list of selectors used to filter nodes."}),(0,t.jsx)(n.td,{children:"[]"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the collector component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the collector image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/collector"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the collector image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the collector container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the collector container."}),(0,t.jsx)(n.td,{children:"7m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.collector.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the collector container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.enabled"}),(0,t.jsx)(n.td,{children:"Whether to enable the scanner component."}),(0,t.jsx)(n.td,{children:"true"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the scanner image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/eraser-trivy-scanner"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the scanner image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the scanner container."}),(0,t.jsx)(n.td,{children:"500Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the scanner container."}),(0,t.jsx)(n.td,{children:"1000m"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.mem"}),(0,t.jsx)(n.td,{children:"The maximum amount of memory the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"2Gi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.limit.cpu"}),(0,t.jsx)(n.td,{children:"The maximum amount of CPU the scanner container is allowed to use."}),(0,t.jsx)(n.td,{children:"0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.scanner.config"}),(0,t.jsx)(n.td,{children:"The configuration to pass to the scanner container, as a YAML string."}),(0,t.jsx)(n.td,{children:"See YAML below"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.repo"}),(0,t.jsx)(n.td,{children:"The repository containing the remover image."}),(0,t.jsx)(n.td,{children:"ghcr.io/eraser-dev/remover"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.image.tag"}),(0,t.jsx)(n.td,{children:"The tag of the remover image."}),(0,t.jsx)(n.td,{children:"v1.0.0"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.mem"}),(0,t.jsx)(n.td,{children:"The amount of memory to request for the remover container."}),(0,t.jsx)(n.td,{children:"25Mi"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"components.remover.request.cpu"}),(0,t.jsx)(n.td,{children:"The amount of CPU to request for the remover container."}),(0,t.jsx)(n.td,{children:"0"})]})]})]})]})}function h(e={}){const{wrapper:n}={...(0,s.a)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},1151:(e,n,r)=>{r.d(n,{Z:()=>a,a:()=>i});var t=r(7294);const s={},o=t.createContext(s);function i(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/fcff9033.b18535a7.js b/docs/assets/js/fcff9033.b18535a7.js deleted file mode 100644 index 9fce4ddcee..0000000000 --- a/docs/assets/js/fcff9033.b18535a7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[4497],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=a.createContext({}),m=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=m(e.components);return a.createElement(s.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},c=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),c=m(n),d=r,g=c["".concat(s,".").concat(d)]||c[d]||u[d]||o;return n?a.createElement(g,l(l({ref:t},p),{},{components:n})):a.createElement(g,l({ref:t},p))}));function d(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,l=new Array(o);l[0]=c;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var m=2;m<o;m++)l[m]=n[m];return a.createElement.apply(null,l)}return a.createElement.apply(null,n)}c.displayName="MDXCreateElement"},7325:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>m});var a=n(7462),r=(n(7294),n(3905));const o={title:"Customization"},l=void 0,i={unversionedId:"customization",id:"customization",title:"Customization",description:"Overview",source:"@site/docs/customization.md",sourceDirName:".",slug:"/customization",permalink:"/eraser/docs/next/customization",draft:!1,tags:[],version:"current",frontMatter:{title:"Customization"},sidebar:"sidebar",previous:{title:"Exclusion",permalink:"/eraser/docs/next/exclusion"},next:{title:"Metrics",permalink:"/eraser/docs/next/metrics"}},s={},m=[{value:"Overview",id:"overview",level:2},{value:"Key Concepts",id:"key-concepts",level:2},{value:"Basic architecture",id:"basic-architecture",level:3},{value:"Scheduling",id:"scheduling",level:3},{value:"Fault Tolerance",id:"fault-tolerance",level:3},{value:"Excluding Nodes",id:"excluding-nodes",level:3},{value:"Configuring Components",id:"configuring-components",level:3},{value:"Swapping out components",id:"swapping-out-components",level:3},{value:"Universal Options",id:"universal-options",level:2},{value:"Component Options",id:"component-options",level:2},{value:"Scanner Options",id:"scanner-options",level:2},{value:"Detailed Options",id:"detailed-options",level:2}],p={toc:m};function u(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"overview"},"Overview"),(0,r.kt)("p",null,"Eraser uses a configmap to configure its behavior. The configmap is part of the\ndeployment and it is not necessary to deploy it manually. Once deployed, the configmap\ncan be edited at any time:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-bash"},"kubectl edit configmap --namespace eraser-system eraser-manager-config\n")),(0,r.kt)("p",null,"If an eraser job is already running, the changes will not take effect until the job completes.\nThe configuration is in yaml."),(0,r.kt)("h2",{id:"key-concepts"},"Key Concepts"),(0,r.kt)("h3",{id:"basic-architecture"},"Basic architecture"),(0,r.kt)("p",null,"The ",(0,r.kt)("em",{parentName:"p"},"manager")," runs as a pod in your cluster and manages ",(0,r.kt)("em",{parentName:"p"},"ImageJobs"),". Think of\nan ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," as a unit of work, performed on every node in your cluster. Each\nnode runs a sub-job. The goal of the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is to assess the images on your\ncluster's nodes, and to remove the images you don't want. There are two stages:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Assessment"),(0,r.kt)("li",{parentName:"ol"},"Removal.")),(0,r.kt)("h3",{id:"scheduling"},"Scheduling"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," can either be created on-demand (see ",(0,r.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/manual-removal"},"Manual Removal"),"),\nor they can be spawned on a timer like a cron job. On-demand jobs skip the\nassessment stage and get right down to the business of removing the images you\nspecified. The behavior of an on-demand job is quite different from that of\ntimed jobs."),(0,r.kt)("h3",{id:"fault-tolerance"},"Fault Tolerance"),(0,r.kt)("p",null,"Because an ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," runs on every node in your cluster, and the conditions on\neach node may vary widely, some of the sub-jobs may fail. If you cannot\ntolerate any failure, set the ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.successRatio")," property to\n",(0,r.kt)("inlineCode",{parentName:"p"},"1.0"),". If 75% success sounds good to you, set it to ",(0,r.kt)("inlineCode",{parentName:"p"},"0.75"),". In that case, if\nfewer than 75% of the pods spawned by the ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," report success, the job as\na whole will be marked as a failure."),(0,r.kt)("p",null,"This is mainly to help diagnose error conditions. As such, you can set\n",(0,r.kt)("inlineCode",{parentName:"p"},"manager.imageJob.cleanup.delayOnFailure")," to a long value so that logs can be\ncaptured before the spawned pods are cleaned up."),(0,r.kt)("h3",{id:"excluding-nodes"},"Excluding Nodes"),(0,r.kt)("p",null,"For various reasons, you may want to prevent Eraser from scheduling pods on\ncertain nodes. To do so, the nodes can be given a special label. By default,\nthis label is ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser.sh/cleanup.filter"),", but you can configure the behavior with\nthe options under ",(0,r.kt)("inlineCode",{parentName:"p"},"manager.nodeFilter"),". The ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table")," provides more detail."),(0,r.kt)("h3",{id:"configuring-components"},"Configuring Components"),(0,r.kt)("p",null,"An ",(0,r.kt)("em",{parentName:"p"},"ImageJob")," is made up of various sub-jobs, with one sub-job for each node.\nThese sub-jobs can be broken down further into three stages."),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"Collection (What is on the node?)"),(0,r.kt)("li",{parentName:"ol"},"Scanning (What images conform to the policy I've provided?)"),(0,r.kt)("li",{parentName:"ol"},"Removal (Remove images based on the results of the above)")),(0,r.kt)("p",null,"Of the above stages, only Removal is mandatory. The others can be disabled.\nFurthermore, manually triggered ",(0,r.kt)("em",{parentName:"p"},"ImageJobs")," will skip right to removal, even if\nEraser is configured to collect and scan. Collection and Scanning will only\ntake place when:"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"The collector and/or scanner ",(0,r.kt)("inlineCode",{parentName:"li"},"components")," are enabled, AND"),(0,r.kt)("li",{parentName:"ol"},"The job was ",(0,r.kt)("em",{parentName:"li"},"not")," triggered manually by creating an ",(0,r.kt)("em",{parentName:"li"},"ImageList"),".")),(0,r.kt)("h3",{id:"swapping-out-components"},"Swapping out components"),(0,r.kt)("p",null,"The collector, scanner, and remover components can all be swapped out. This\nenables you to build and host the images yourself. In addition, the scanner's\nbehavior can be completely tailored to your needs by swapping out the default\nimage with one of your own. To specify the images, use the\n",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.repo")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"components.<component>.image.tag"),",\nwhere ",(0,r.kt)("inlineCode",{parentName:"p"},"<component>")," is one of ",(0,r.kt)("inlineCode",{parentName:"p"},"collector"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"scanner"),", or ",(0,r.kt)("inlineCode",{parentName:"p"},"remover"),"."),(0,r.kt)("h2",{id:"universal-options"},"Universal Options"),(0,r.kt)("p",null,"The following portions of the configmap apply no matter how you spawn your\n",(0,r.kt)("em",{parentName:"p"},"ImageJob"),". The values provided below are the defaults. For more detail on\nthese options, see the ",(0,r.kt)("a",{parentName:"p",href:"#detailed-options"},"table"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},'manager:\n runtime:\n name: containerd\n address: unix:///run/containerd/containerd.sock\n otlpEndpoint: "" # empty string disables OpenTelemetry\n logLevel: info\n profile:\n enabled: false\n port: 6060\n imageJob:\n successRatio: 1.0\n cleanup:\n delayOnSuccess: 0s\n delayOnFailure: 24h\n pullSecrets: [] # image pull secrets for collector/scanner/remover\n priorityClassName: "" # priority class name for collector/scanner/remover\n nodeFilter:\n type: exclude # must be either exclude|include\n selectors:\n - eraser.sh/cleanup.filter\n - kubernetes.io/os=windows\ncomponents:\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n')),(0,r.kt)("h2",{id:"component-options"},"Component Options"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"components:\n collector:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/collector\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 7m\n limit:\n mem: 500Mi\n cpu: 0\n scanner:\n enabled: true\n image:\n repo: ghcr.io/eraser-dev/eraser-trivy-scanner\n tag: v1.0.0\n request:\n mem: 500Mi\n cpu: 1000m\n limit:\n mem: 2Gi\n cpu: 0\n config: |\n # this is the schema for the provided 'trivy-scanner'. custom scanners\n # will define their own configuration. see the below\n remover:\n image:\n repo: ghcr.io/eraser-dev/remover\n tag: v1.0.0\n request:\n mem: 25Mi\n cpu: 0\n limit:\n mem: 30Mi\n cpu: 1000m\n")),(0,r.kt)("h2",{id:"scanner-options"},"Scanner Options"),(0,r.kt)("p",null,"These options can be provided to ",(0,r.kt)("inlineCode",{parentName:"p"},"components.scanner.config"),". They will be\npassed through as a string to the scanner container and parsed there. If you\nwant to configure your own scanner, you must provide some way to parse this."),(0,r.kt)("p",null,"Below are the values recognized by the provided ",(0,r.kt)("inlineCode",{parentName:"p"},"eraser-trivy-scanner")," image.\nValues provided below are the defaults."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-yaml"},"cacheDir: /var/lib/trivy # The file path inside the container to store the cache\ndbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database\ndeleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed\ndeleteEOLImages: true # if true, remove images that have reached their end-of-life date\nvulnerabilities:\n ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.\n types: # a list of vulnerability types. for more info, see trivy's documentation.\n - os\n - library\n securityChecks: # see trivy's documentation for more information\n - vuln\n severities: # in this case, only flag images with CRITICAL vulnerability for removal\n - CRITICAL\n ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.\ntimeout:\n total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan\n perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted\n")),(0,r.kt)("h2",{id:"detailed-options"},"Detailed Options"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null},"Option"),(0,r.kt)("th",{parentName:"tr",align:null},"Description"),(0,r.kt)("th",{parentName:"tr",align:null},"Default"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime.name"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes."),(0,r.kt)("td",{parentName:"tr",align:null},"containerd")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.runtime.address"),(0,r.kt)("td",{parentName:"tr",align:null},"The runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions."),(0,r.kt)("td",{parentName:"tr",align:null},"unix:///run/containerd/containerd.sock")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.otlpEndpoint"),(0,r.kt)("td",{parentName:"tr",align:null},"The endpoint to send OpenTelemetry data to. If empty, data will not be sent."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.logLevel"),(0,r.kt)("td",{parentName:"tr",align:null},"The log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal."),(0,r.kt)("td",{parentName:"tr",align:null},"info")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.repeatInterval"),(0,r.kt)("td",{parentName:"tr",align:null},"Use only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," at the interval provided."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.scheduling.beginImmediately"),(0,r.kt)("td",{parentName:"tr",align:null},"If set to true, the fist ",(0,r.kt)("em",{parentName:"td"},"ImageJob")," will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable profiling for the manager's containers. This is for debugging with ",(0,r.kt)("inlineCode",{parentName:"td"},"go tool pprof"),"."),(0,r.kt)("td",{parentName:"tr",align:null},"false")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.profile.port"),(0,r.kt)("td",{parentName:"tr",align:null},"The port on which to expose the profiling endpoint."),(0,r.kt)("td",{parentName:"tr",align:null},"6060")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.successRatio"),(0,r.kt)("td",{parentName:"tr",align:null},"The ratio of successful image jobs required before a cleanup is performed."),(0,r.kt)("td",{parentName:"tr",align:null},"1.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnSuccess"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a successful image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"0s")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.imageJob.cleanup.delayOnFailure"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of time to wait after a failed image job before performing cleanup."),(0,r.kt)("td",{parentName:"tr",align:null},"24h")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.pullSecrets"),(0,r.kt)("td",{parentName:"tr",align:null},"The image pull secrets to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.priorityClassName"),(0,r.kt)("td",{parentName:"tr",align:null},"The priority class to use for collector, scanner, and remover containers."),(0,r.kt)("td",{parentName:"tr",align:null},'""')),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.type"),(0,r.kt)("td",{parentName:"tr",align:null},'The type of node filter to use. Must be either "exclude" or "include".'),(0,r.kt)("td",{parentName:"tr",align:null},"exclude")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"manager.nodeFilter.selectors"),(0,r.kt)("td",{parentName:"tr",align:null},"A list of selectors used to filter nodes."),(0,r.kt)("td",{parentName:"tr",align:null},"[]")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the collector component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/collector")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the collector image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the collector container."),(0,r.kt)("td",{parentName:"tr",align:null},"7m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.collector.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the collector container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.enabled"),(0,r.kt)("td",{parentName:"tr",align:null},"Whether to enable the scanner component."),(0,r.kt)("td",{parentName:"tr",align:null},"true")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/eraser-trivy-scanner")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the scanner image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"500Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the scanner container."),(0,r.kt)("td",{parentName:"tr",align:null},"1000m")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of memory the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"2Gi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.limit.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The maximum amount of CPU the scanner container is allowed to use."),(0,r.kt)("td",{parentName:"tr",align:null},"0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.scanner.config"),(0,r.kt)("td",{parentName:"tr",align:null},"The configuration to pass to the scanner container, as a YAML string."),(0,r.kt)("td",{parentName:"tr",align:null},"See YAML below")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.repo"),(0,r.kt)("td",{parentName:"tr",align:null},"The repository containing the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"ghcr.io/eraser-dev/remover")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.image.tag"),(0,r.kt)("td",{parentName:"tr",align:null},"The tag of the remover image."),(0,r.kt)("td",{parentName:"tr",align:null},"v1.0.0")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.mem"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of memory to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"25Mi")),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},"components.remover.request.cpu"),(0,r.kt)("td",{parentName:"tr",align:null},"The amount of CPU to request for the remover container."),(0,r.kt)("td",{parentName:"tr",align:null},"0")))))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/fd1ae250.0fe36588.js b/docs/assets/js/fd1ae250.0fe36588.js deleted file mode 100644 index c1a595143c..0000000000 --- a/docs/assets/js/fd1ae250.0fe36588.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5221],{3905:(e,r,t)=>{t.d(r,{Zo:()=>l,kt:()=>v});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?i(Object(t),!0).forEach((function(r){o(e,r,t[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r))}))}return e}function c(e,r){if(null==e)return{};var t,n,o=function(e,r){if(null==e)return{};var t,n,o={},i=Object.keys(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)t=i[n],r.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),p=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},l=function(e){var r=p(e.components);return n.createElement(s.Provider,{value:r},e.children)},u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},f=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),f=p(t),v=o,y=f["".concat(s,".").concat(v)]||f[v]||u[v]||i;return t?n.createElement(y,a(a({ref:r},l),{},{components:t})):n.createElement(y,a({ref:r},l))}));function v(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=f;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,a[1]=c;for(var p=2;p<i;p++)a[p]=t[p];return n.createElement.apply(null,a)}return n.createElement.apply(null,t)}f.displayName="MDXCreateElement"},1458:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>s,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i={title:"Trivy"},a=void 0,c={unversionedId:"trivy",id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/docs/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/next/trivy",draft:!1,tags:[],version:"current",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/next/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/next/faq"}},s={},p=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}],l={toc:p};function u(e){let{components:r,...t}=e;return(0,o.kt)("wrapper",(0,n.Z)({},l,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"trivy-provider-options"},"Trivy Provider Options"),(0,o.kt)("p",null,"The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,o.kt)("a",{parentName:"p",href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options"},"Customization")," for more details on configuring the scanner."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/fd1ae250.8a9454eb.js b/docs/assets/js/fd1ae250.8a9454eb.js new file mode 100644 index 0000000000..daf6aa13ed --- /dev/null +++ b/docs/assets/js/fd1ae250.8a9454eb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5221],{7105:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>p,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var n=r(5893),i=r(1151);const o={title:"Trivy"},s=void 0,a={id:"trivy",title:"Trivy",description:"Trivy Provider Options",source:"@site/docs/trivy.md",sourceDirName:".",slug:"/trivy",permalink:"/eraser/docs/next/trivy",draft:!1,unlisted:!1,tags:[],version:"current",frontMatter:{title:"Trivy"},sidebar:"sidebar",previous:{title:"Custom Scanner",permalink:"/eraser/docs/next/custom-scanner"},next:{title:"FAQ",permalink:"/eraser/docs/next/faq"}},c={},d=[{value:"Trivy Provider Options",id:"trivy-provider-options",level:2}];function u(e){const t={a:"a",h2:"h2",p:"p",...(0,i.a)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h2,{id:"trivy-provider-options",children:"Trivy Provider Options"}),"\n",(0,n.jsxs)(t.p,{children:["The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See ",(0,n.jsx)(t.a,{href:"https://eraser-dev.github.io/eraser/docs/customization#scanner-options",children:"Customization"})," for more details on configuring the scanner."]})]})}function p(e={}){const{wrapper:t}={...(0,i.a)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},1151:(e,t,r)=>{r.d(t,{Z:()=>a,a:()=>s});var n=r(7294);const i={},o=n.createContext(i);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/main.3fdea3bd.js b/docs/assets/js/main.3fdea3bd.js deleted file mode 100644 index 6a535e27f2..0000000000 --- a/docs/assets/js/main.3fdea3bd.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.3fdea3bd.js.LICENSE.txt */ -(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[179],{830:(e,t,n)=>{"use strict";n.d(t,{W:()=>a});var r=n(7294);function a(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},4334:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(n=r(e[t]))&&(a&&(a+=" "),a+=n);else for(t in e)e[t]&&(a&&(a+=" "),a+=t);return a}n.d(t,{Z:()=>a});const a=function(){for(var e,t,n=0,a="";n<arguments.length;)(e=arguments[n++])&&(t=r(e))&&(a&&(a+=" "),a+=t);return a}},1205:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var a,o;switch(n=n||{},r.util.type(t)){case"Object":if(o=r.util.objId(t),n[o])return n[o];for(var i in a={},n[o]=a,t)t.hasOwnProperty(i)&&(a[i]=e(t[i],n));return a;case"Array":return o=r.util.objId(t),n[o]?n[o]:(a=[],n[o]=a,t.forEach((function(t,r){a[r]=e(t,n)})),a);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var r="no-"+t;e;){var a=e.classList;if(a.contains(t))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var a in t)n[a]=t[a];return n},insertBefore:function(e,t,n,a){var o=(a=a||r.languages)[e],i={};for(var s in o)if(o.hasOwnProperty(s)){if(s==t)for(var l in n)n.hasOwnProperty(l)&&(i[l]=n[l]);n.hasOwnProperty(s)||(i[s]=o[s])}var c=a[e];return a[e]=i,r.languages.DFS(r.languages,(function(t,n){n===c&&t!=e&&(this[t]=i)})),i},DFS:function e(t,n,a,o){o=o||{};var i=r.util.objId;for(var s in t)if(t.hasOwnProperty(s)){n.call(t,s,t[s],a||s);var l=t[s],c=r.util.type(l);"Object"!==c||o[i(l)]?"Array"!==c||o[i(l)]||(o[i(l)]=!0,e(l,n,s,o)):(o[i(l)]=!0,e(l,n,null,o))}}},plugins:{},highlight:function(e,t,n){var o={code:e,grammar:t,language:n};return r.hooks.run("before-tokenize",o),o.tokens=r.tokenize(o.code,o.grammar),r.hooks.run("after-tokenize",o),a.stringify(r.util.encode(o.tokens),o.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var r in n)t[r]=n[r];delete t.rest}var a=new s;return l(a,a.head,e),i(e,a,t,a.head,0),function(e){var t=[],n=e.head.next;for(;n!==e.tail;)t.push(n.value),n=n.next;return t}(a)},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var a,o=0;a=n[o++];)a(t)}},Token:a};function a(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function o(e,t,n,r){e.lastIndex=t;var a=e.exec(n);if(a&&r&&a[1]){var o=a[1].length;a.index+=o,a[0]=a[0].slice(o)}return a}function i(e,t,n,s,u,d){for(var f in n)if(n.hasOwnProperty(f)&&n[f]){var p=n[f];p=Array.isArray(p)?p:[p];for(var m=0;m<p.length;++m){if(d&&d.cause==f+","+m)return;var h=p[m],g=h.inside,v=!!h.lookbehind,b=!!h.greedy,y=h.alias;if(b&&!h.pattern.global){var w=h.pattern.toString().match(/[imsuy]*$/)[0];h.pattern=RegExp(h.pattern.source,w+"g")}for(var x=h.pattern||h,k=s.next,E=u;k!==t.tail&&!(d&&E>=d.reach);E+=k.value.length,k=k.next){var S=k.value;if(t.length>e.length)return;if(!(S instanceof a)){var _,C=1;if(b){if(!(_=o(x,E,e,v))||_.index>=e.length)break;var T=_.index,A=_.index+_[0].length,L=E;for(L+=k.value.length;T>=L;)L+=(k=k.next).value.length;if(E=L-=k.value.length,k.value instanceof a)continue;for(var R=k;R!==t.tail&&(L<A||"string"==typeof R.value);R=R.next)C++,L+=R.value.length;C--,S=e.slice(E,L),_.index-=E}else if(!(_=o(x,0,S,v)))continue;T=_.index;var N=_[0],P=S.slice(0,T),O=S.slice(T+N.length),I=E+S.length;d&&I>d.reach&&(d.reach=I);var D=k.prev;if(P&&(D=l(t,D,P),E+=P.length),c(t,D,C),k=l(t,D,new a(f,g?r.tokenize(N,g):N,y,N)),O&&l(t,k,O),C>1){var M={cause:f+","+m,reach:I};i(e,t,n,k.prev,E,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function c(e,t,n){for(var r=t.next,a=0;a<n&&r!==e.tail;a++)r=r.next;t.next=r,r.prev=t,e.length-=a}return a.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var a="";return t.forEach((function(t){a+=e(t,n)})),a}var o={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},i=t.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(o.classes,i):o.classes.push(i)),r.hooks.run("wrap",o);var s="";for(var l in o.attributes)s+=" "+l+'="'+(o.attributes[l]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+s+">"+o.content+"</"+o.tag+">"},r}(),a=r;r.default=r,a.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.languages.markup.doctype.inside["internal-subset"].inside=a.languages.markup,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i;var r={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(a.languages.markup.tag,"addAttribute",{value:function(e,t){a.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:a.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.xml=a.languages.extend("markup",{}),a.languages.ssml=a.languages.xml,a.languages.atom=a.languages.xml,a.languages.rss=a.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i<a.length;i++)o[a[i]]=e.languages.bash[a[i]];e.languages.shell=e.languages.bash}(a),a.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),a.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),a.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},a.languages.c.string],char:a.languages.c.char,comment:a.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:a.languages.c}}}}),a.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete a.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(a),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(a),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:a})}(a),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:a.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),a.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),a.languages.markup&&(a.languages.markup.tag.addInlined("script","javascript"),a.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),a.languages.js=a.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(a),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n<r;n++){var a=t[n];if("code"===a.type){var o=a.content[1],i=a.content[3];if(o&&i&&"code-language"===o.type&&"code-block"===i.type&&"string"==typeof o.content){var s=o.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),l="language-"+(s=(/[a-z][\w-]*/i.exec(s)||[""])[0].toLowerCase());i.alias?"string"==typeof i.alias?i.alias=[i.alias,l]:i.alias.push(l):i.alias=[l]}}else e(a.content)}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",r=0,a=t.classes.length;r<a;r++){var o=t.classes[r],c=/language-(.+)/.exec(o);if(c){n=c[1];break}}var u,d=e.languages[n];if(d)t.content=e.highlight((u=t.content,u.replace(i,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;if("#"===(t=t.toLowerCase())[0])return n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),l(n);var r=s[t];return r||e}))),d,n);else if(n&&"none"!==n&&e.plugins.autoloader){var f="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random());t.attributes.id=f,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(f);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))}))}}}));var i=RegExp(e.languages.markup.tag.pattern.source,"gi"),s={amp:"&",lt:"<",gt:">",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(a),a.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:a.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},a.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var r=t[n++];if("keyword"===r.type&&"mutation"===r.content){var a=[];if(d(["definition-mutation","punctuation"])&&"("===u(1).content){n+=2;var o=f(/^\($/,/^\)$/);if(-1===o)continue;for(;n<o;n++){var i=u(0);"variable"===i.type&&(p(i,"variable-input"),a.push(i.content))}n=o+1}if(d(["punctuation","property-query"])&&"{"===u(0).content&&(n++,p(u(0),"property-mutation"),a.length>0)){var s=f(/^\{$/,/^\}$/);if(-1===s)continue;for(var l=n;l<s;l++){var c=t[l];"variable"===c.type&&a.indexOf(c.content)>=0&&p(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var r=u(n+t);if(!r||r.type!==e[n])return!1}return!0}function f(e,r){for(var a=1,o=n;o<t.length;o++){var i=t[o],s=i.content;if("punctuation"===i.type&&"string"==typeof s)if(e.test(s))a++;else if(r.test(s)&&0===--a)return o}return-1}function p(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),a.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function c(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function u(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,u={},d=l(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=s(i++,r)););return u[n]=a,n})).join(""),n,r),f=Object.keys(u);return i=0,function e(t){for(var n=0;n<t.length;n++){if(i>=f.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=f[i],o="string"==typeof r?r:r.content,s=o.indexOf(a);if(-1!==s){++i;var l=o.substring(0,s),d=c(u[a]),p=o.substring(s+a.length),m=[];if(l&&m.push(l),m.push(d),p){var h=[p];e(h),m.push.apply(m,h)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var g=r.content;Array.isArray(g)?e(g):e([g])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,a=n.length;r<a;r++){var o=n[r];if("string"!=typeof o){var i=o.content;if(Array.isArray(i))if("template-string"===o.type){var s=i[1];if(3===i.length&&"string"!=typeof s&&"embedded-code"===s.type){var l=f(s),c=s.alias,d=Array.isArray(c)?c[0]:c,p=e.languages[d];if(!p)continue;i[1]=u(l,p,d)}}else t(i);else"string"!=typeof i&&t([i])}}}(t.tokens)}))}(a),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(a),function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r<n.length;r++){var a=n[r],o=e.languages.javascript[a];"RegExp"===e.util.type(o)&&(o=e.languages.javascript[a]={pattern:o});var i=o.inside||{};o.inside=i,i["maybe-class-name"]=/^[A-Z][\s\S]*/}}(a),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,a=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function o(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return r})).replace(/<SPREAD>/g,(function(){return a})),RegExp(e,t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},s=function(t){for(var n=[],r=0;r<t.length;r++){var a=t[r],o=!1;if("string"!=typeof a&&("tag"===a.type&&a.content[0]&&"tag"===a.content[0].type?"</"===a.content[0].content[0].content?n.length>0&&n[n.length-1].tagName===i(a.content[0].content[1])&&n.pop():"/>"===a.content[a.content.length-1].content||n.push({tagName:i(a.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&n.length>0&&0===n[n.length-1].openedBraces){var l=i(a);r<t.length-1&&("string"==typeof t[r+1]||"plain-text"===t[r+1].type)&&(l+=i(t[r+1]),t.splice(r+1,1)),r>0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(l=i(t[r-1])+l,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",l,null,l)}a.content&&"string"!=typeof a.content&&s(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||s(e.tokens)}))}(a),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),a.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete a.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,s=i.length;-1!==n.code.indexOf(a=t(r,s));)++s;return i[s]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l<s.length&&!(a>=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[a],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(r,u),m=f.indexOf(p);if(m>-1){++a;var h=f.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),v=f.substring(m+p.length),b=[];h&&b.push.apply(b,i([h])),b.push(g),v&&b.push.apply(b,i([v])),"string"==typeof c?s.splice.apply(s,[l,1].concat(b)):c.content=b}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(a),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(a),a.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.webmanifest=a.languages.json,a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.objc=a.languages.objectivec,a.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),a.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},r={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};r.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:r}},r.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:r}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:r}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:r}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:r}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:r.interpolation}},rest:r}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:r.interpolation,comment:r.comment,punctuation:/[{},]/}},func:r.func,string:r.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:r.interpolation,punctuation:/[{}()\[\];:.]/}}(a),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(a),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=a},7459:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t<e.length;t++)e[t]&&(n=r(e[t]))&&(a&&(a+=" "),a+=n);else for(t in e)e[t]&&(a&&(a+=" "),a+=t);return a}n.d(t,{Z:()=>a});const a=function(){for(var e,t,n=0,a="";n<arguments.length;)(e=arguments[n++])&&(t=r(e))&&(a&&(a+=" "),a+=t);return a}},723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7294),a=n(7462),o=n(8356),i=n.n(o),s=n(6887);const l={"0390b328":[()=>n.e(7868).then(n.bind(n,5807)),"@site/versioned_docs/version-v0.5.x/custom-scanner.md",5807],"0480b142":[()=>n.e(836).then(n.bind(n,3584)),"@site/docs/faq.md",3584],"07e6d80c":[()=>n.e(3939).then(n.bind(n,7882)),"@site/versioned_docs/version-v1.2.x/exclusion.md",7882],"096837f0":[()=>n.e(6013).then(n.bind(n,9418)),"@site/versioned_docs/version-v1.1.x/manual-removal.md",9418],"0a1e161c":[()=>n.e(5841).then(n.t.bind(n,7085,19)),"/home/runner/work/eraser/eraser/docs/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",7085],"0d9a188d":[()=>n.e(1865).then(n.bind(n,7970)),"@site/versioned_docs/version-v0.5.x/contributing.md",7970],"0fb10398":[()=>n.e(4781).then(n.bind(n,1126)),"@site/versioned_docs/version-v1.2.x/setup.md",1126],"101be56a":[()=>n.e(7029).then(n.bind(n,8611)),"@site/versioned_docs/version-v1.2.x/quick-start.md",8611],"11d58a17":[()=>n.e(154).then(n.bind(n,9971)),"@site/versioned_docs/version-v0.5.x/code-of-conduct.md",9971],12682444:[()=>n.e(3514).then(n.bind(n,8058)),"@site/versioned_docs/version-v0.5.x/customization.md",8058],17896441:[()=>Promise.all([n.e(532),n.e(7918)]).then(n.bind(n,3230)),"@theme/DocItem",3230],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,4998)),"@theme/SearchPage",4998],"1b064146":[()=>n.e(4178).then(n.bind(n,3648)),"@site/docs/release-management.md",3648],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1c30975d":[()=>n.e(3996).then(n.bind(n,115)),"@site/versioned_docs/version-v0.4.x/customization.md",115],"1dba1ecf":[()=>n.e(2510).then(n.bind(n,3918)),"@site/docs/metrics.md",3918],"20cdecc4":[()=>n.e(391).then(n.bind(n,4092)),"@site/versioned_docs/version-v0.5.x/manual-removal.md",4092],"22539a87":[()=>n.e(5964).then(n.bind(n,9684)),"@site/versioned_docs/version-v0.4.x/introduction.md",9684],"24e97898":[()=>n.e(5781).then(n.bind(n,7536)),"@site/versioned_docs/version-v0.4.x/architecture.md",7536],"29ca1a0e":[()=>n.e(5873).then(n.bind(n,1261)),"@site/versioned_docs/version-v1.1.x/custom-scanner.md",1261],"2c8b636f":[()=>n.e(1763).then(n.bind(n,7395)),"@site/versioned_docs/version-v0.4.x/releasing.md",7395],"2f4673e5":[()=>n.e(216).then(n.bind(n,184)),"@site/versioned_docs/version-v1.1.x/metrics.md",184],"30fb9660":[()=>n.e(3902).then(n.bind(n,9434)),"@site/versioned_docs/version-v1.3.x/faq.md",9434],"34f2f592":[()=>n.e(9269).then(n.bind(n,5374)),"@site/versioned_docs/version-v0.5.x/quick-start.md",5374],"3847b3ea":[()=>n.e(5581).then(n.bind(n,1959)),"@site/docs/setup.md",1959],"3a1ed2bb":[()=>n.e(2389).then(n.bind(n,2308)),"@site/versioned_docs/version-v1.2.x/faq.md",2308],"3b8c55ea":[()=>n.e(3217).then(n.bind(n,9250)),"@site/docs/installation.md",9250],"3e4c86d4":[()=>n.e(8180).then(n.t.bind(n,9424,19)),"~docs/default/version-v-1-1-x-metadata-prop-f22.json",9424],"3fcb412e":[()=>n.e(3242).then(n.bind(n,1450)),"@site/versioned_docs/version-v0.4.x/installation.md",1450],"422308df":[()=>n.e(4642).then(n.t.bind(n,1865,19)),"~docs/default/version-v-1-2-x-metadata-prop-53a.json",1865],"4351fb58":[()=>n.e(7551).then(n.bind(n,1153)),"@site/versioned_docs/version-v1.0.x/faq.md",1153],"44b2adf6":[()=>n.e(8841).then(n.bind(n,2650)),"@site/versioned_docs/version-v1.3.x/trivy.md",2650],"48ae5635":[()=>n.e(9212).then(n.bind(n,6954)),"@site/versioned_docs/version-v0.4.x/contributing.md",6954],"4d54d076":[()=>n.e(7080).then(n.bind(n,1933)),"@site/docs/contributing.md",1933],"4eac74de":[()=>n.e(2547).then(n.bind(n,8475)),"@site/versioned_docs/version-v0.4.x/custom-scanner.md",8475],"4fa03c51":[()=>n.e(7395).then(n.bind(n,7422)),"@site/docs/manual-removal.md",7422],"4fb2362d":[()=>n.e(4248).then(n.t.bind(n,6198,19)),"~docs/default/version-v-1-3-x-metadata-prop-1ab.json",6198],"5281b7a2":[()=>n.e(5927).then(n.bind(n,1527)),"@site/docs/architecture.md",1527],"5603335d":[()=>n.e(1031).then(n.bind(n,1307)),"@site/docs/custom-scanner.md",1307],"59e5a646":[()=>n.e(3022).then(n.bind(n,3065)),"@site/versioned_docs/version-v1.1.x/setup.md",3065],"5af9b662":[()=>n.e(5523).then(n.bind(n,4478)),"@site/versioned_docs/version-v1.0.x/releasing.md",4478],"5bc37772":[()=>n.e(8084).then(n.bind(n,372)),"@site/versioned_docs/version-v1.2.x/releasing.md",372],"5c838b7d":[()=>n.e(2242).then(n.bind(n,6874)),"@site/versioned_docs/version-v1.3.x/customization.md",6874],"621c6848":[()=>n.e(7497).then(n.t.bind(n,3769,19)),"/home/runner/work/eraser/eraser/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"62c6dc45":[()=>n.e(6252).then(n.bind(n,6634)),"@site/versioned_docs/version-v1.0.x/exclusion.md",6634],"6739d7ff":[()=>n.e(5384).then(n.bind(n,5088)),"@site/versioned_docs/version-v1.2.x/installation.md",5088],"695a8bbb":[()=>n.e(7220).then(n.t.bind(n,9491,19)),"~docs/default/version-v-1-0-x-metadata-prop-19b.json",9491],"6af0c1ea":[()=>n.e(5954).then(n.bind(n,1336)),"@site/versioned_docs/version-v1.0.x/trivy.md",1336],"6b8e46b3":[()=>n.e(7499).then(n.bind(n,6370)),"@site/versioned_docs/version-v1.3.x/code-of-conduct.md",6370],"6ec64a11":[()=>n.e(5255).then(n.bind(n,5952)),"@site/versioned_docs/version-v1.0.x/setup.md",5952],"70b084fe":[()=>n.e(9291).then(n.bind(n,9828)),"@site/versioned_docs/version-v1.1.x/architecture.md",9828],"7196cdd1":[()=>n.e(4404).then(n.bind(n,9743)),"@site/versioned_docs/version-v1.2.x/custom-scanner.md",9743],"72e14192":[()=>n.e(7239).then(n.bind(n,4181)),"@site/docs/quick-start.md",4181],"72ffabc7":[()=>n.e(8301).then(n.bind(n,2575)),"@site/versioned_docs/version-v1.0.x/installation.md",2575],"7b11c903":[()=>n.e(5178).then(n.bind(n,8965)),"@site/docs/exclusion.md",8965],"7c6883b5":[()=>n.e(783).then(n.bind(n,5222)),"@site/versioned_docs/version-v1.1.x/installation.md",5222],"7d415946":[()=>n.e(6705).then(n.bind(n,8134)),"@site/docs/releasing.md",8134],"7d6336d8":[()=>n.e(3052).then(n.bind(n,1594)),"@site/versioned_docs/version-v1.3.x/installation.md",1594],"85c70040":[()=>n.e(3695).then(n.bind(n,8741)),"@site/versioned_docs/version-v1.3.x/introduction.md",8741],"8c9fcf50":[()=>n.e(4345).then(n.bind(n,5427)),"@site/versioned_docs/version-v1.0.x/manual-removal.md",5427],"8cd4fd18":[()=>n.e(1190).then(n.bind(n,3314)),"@site/versioned_docs/version-v1.0.x/contributing.md",3314],"8eef7690":[()=>n.e(40).then(n.bind(n,4488)),"@site/versioned_docs/version-v0.5.x/setup.md",4488],"8f41530a":[()=>n.e(4292).then(n.bind(n,7137)),"@site/versioned_docs/version-v1.1.x/code-of-conduct.md",7137],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"93bf47d2":[()=>n.e(2288).then(n.bind(n,3873)),"@site/versioned_docs/version-v1.3.x/metrics.md",3873],"974203ee":[()=>n.e(1351).then(n.bind(n,5490)),"@site/versioned_docs/version-v1.2.x/customization.md",5490],"9748995c":[()=>n.e(8050).then(n.bind(n,9046)),"@site/versioned_docs/version-v1.0.x/quick-start.md",9046],"99ed3086":[()=>n.e(5593).then(n.bind(n,7223)),"@site/versioned_docs/version-v1.0.x/customization.md",7223],"9d55bf96":[()=>n.e(2238).then(n.bind(n,6891)),"@site/versioned_docs/version-v1.3.x/exclusion.md",6891],"9dbb4f95":[()=>n.e(6842).then(n.bind(n,7101)),"@site/versioned_docs/version-v1.0.x/introduction.md",7101],"9e350ec0":[()=>n.e(7262).then(n.bind(n,6937)),"@site/versioned_docs/version-v0.4.x/quick-start.md",6937],"9ff53b5b":[()=>n.e(9829).then(n.bind(n,4129)),"@site/versioned_docs/version-v1.3.x/custom-scanner.md",4129],a09c2993:[()=>n.e(4128).then(n.bind(n,8495)),"@site/docs/introduction.md",8495],a683e47f:[()=>n.e(846).then(n.bind(n,1805)),"@site/versioned_docs/version-v0.5.x/releasing.md",1805],a708fa78:[()=>n.e(2356).then(n.bind(n,2472)),"@site/versioned_docs/version-v1.2.x/code-of-conduct.md",2472],a8f67d08:[()=>n.e(7591).then(n.bind(n,4157)),"@site/versioned_docs/version-v1.2.x/contributing.md",4157],a932041a:[()=>n.e(5754).then(n.bind(n,4906)),"@site/versioned_docs/version-v0.4.x/setup.md",4906],ae417a11:[()=>n.e(6300).then(n.bind(n,3386)),"@site/versioned_docs/version-v1.3.x/quick-start.md",3386],b0fc3de5:[()=>n.e(2005).then(n.bind(n,6601)),"@site/versioned_docs/version-v1.0.x/metrics.md",6601],b70ea2cb:[()=>n.e(2534).then(n.bind(n,4446)),"@site/versioned_docs/version-v1.1.x/releasing.md",4446],b7730d0d:[()=>n.e(8976).then(n.bind(n,1874)),"@site/versioned_docs/version-v1.2.x/trivy.md",1874],b7cd4035:[()=>n.e(2229).then(n.bind(n,2014)),"@site/versioned_docs/version-v1.3.x/releasing.md",2014],b9421f89:[()=>n.e(7114).then(n.bind(n,550)),"@site/versioned_docs/version-v0.4.x/faq.md",550],bacc1ae0:[()=>n.e(2579).then(n.bind(n,9955)),"@site/versioned_docs/version-v1.3.x/contributing.md",9955],bbedbacb:[()=>n.e(3523).then(n.bind(n,9276)),"@site/versioned_docs/version-v1.2.x/architecture.md",9276],bc344202:[()=>n.e(6534).then(n.bind(n,6279)),"@site/versioned_docs/version-v1.3.x/architecture.md",6279],bc8dcae3:[()=>n.e(4815).then(n.bind(n,2289)),"@site/versioned_docs/version-v1.3.x/manual-removal.md",2289],bdb5eb86:[()=>n.e(8411).then(n.bind(n,3591)),"@site/versioned_docs/version-v1.0.x/architecture.md",3591],bf5c5542:[()=>n.e(548).then(n.bind(n,2241)),"@site/versioned_docs/version-v0.5.x/trivy.md",2241],bffae3e7:[()=>n.e(7092).then(n.bind(n,3707)),"@site/versioned_docs/version-v1.1.x/contributing.md",3707],c108e81c:[()=>n.e(2156).then(n.bind(n,2852)),"@site/versioned_docs/version-v0.4.x/manual-removal.md",2852],c12dc9fd:[()=>n.e(6325).then(n.bind(n,4606)),"@site/versioned_docs/version-v0.4.x/code-of-conduct.md",4606],c4f50fcb:[()=>n.e(907).then(n.bind(n,7644)),"@site/versioned_docs/version-v1.2.x/introduction.md",7644],c66bbf8a:[()=>n.e(568).then(n.bind(n,789)),"@site/versioned_docs/version-v0.5.x/introduction.md",789],c698fe77:[()=>n.e(4993).then(n.t.bind(n,6283,19)),"~docs/default/version-v-0-4-x-metadata-prop-1ae.json",6283],c73303db:[()=>n.e(5082).then(n.bind(n,2992)),"@site/versioned_docs/version-v0.5.x/installation.md",2992],c853dc39:[()=>n.e(7028).then(n.bind(n,2001)),"@site/versioned_docs/version-v1.3.x/setup.md",2001],c9ca4745:[()=>n.e(5243).then(n.bind(n,4879)),"@site/versioned_docs/version-v1.1.x/introduction.md",4879],d40dbec5:[()=>n.e(7677).then(n.bind(n,2646)),"@site/versioned_docs/version-v0.4.x/exclusion.md",2646],d7561401:[()=>n.e(9214).then(n.bind(n,2077)),"@site/versioned_docs/version-v1.0.x/custom-scanner.md",2077],db59132a:[()=>n.e(1619).then(n.bind(n,8394)),"@site/versioned_docs/version-v1.1.x/quick-start.md",8394],dbbf7db4:[()=>n.e(5245).then(n.bind(n,9209)),"@site/versioned_docs/version-v1.0.x/code-of-conduct.md",9209],dc9281b9:[()=>n.e(895).then(n.bind(n,8561)),"@site/versioned_docs/version-v1.1.x/customization.md",8561],dea0f9ea:[()=>n.e(6352).then(n.bind(n,6853)),"@site/docs/code-of-conduct.md",6853],e1b2cf59:[()=>n.e(2023).then(n.bind(n,1766)),"@site/versioned_docs/version-v1.1.x/trivy.md",1766],e36340b6:[()=>n.e(9722).then(n.bind(n,1635)),"@site/versioned_docs/version-v1.1.x/exclusion.md",1635],e3d8f98f:[()=>n.e(6236).then(n.bind(n,6040)),"@site/versioned_docs/version-v1.2.x/metrics.md",6040],e7fdf6d9:[()=>n.e(643).then(n.bind(n,7016)),"@site/versioned_docs/version-v1.3.x/release-management.md",7016],ec0d5d9e:[()=>n.e(1760).then(n.bind(n,7125)),"@site/versioned_docs/version-v0.5.x/architecture.md",7125],ed8448fe:[()=>n.e(1857).then(n.bind(n,4552)),"@site/versioned_docs/version-v1.2.x/manual-removal.md",4552],efdb11b6:[()=>n.e(4111).then(n.t.bind(n,7064,19)),"~docs/default/version-v-0-5-x-metadata-prop-c47.json",7064],f2ef54d0:[()=>n.e(6039).then(n.bind(n,6782)),"@site/versioned_docs/version-v1.1.x/faq.md",6782],fa2b770f:[()=>n.e(6148).then(n.bind(n,9974)),"@site/versioned_docs/version-v0.5.x/faq.md",9974],faa9d310:[()=>n.e(6578).then(n.bind(n,5354)),"@site/versioned_docs/version-v0.4.x/trivy.md",5354],fc618254:[()=>n.e(4428).then(n.bind(n,5055)),"@site/versioned_docs/version-v0.5.x/exclusion.md",5055],fcff9033:[()=>n.e(4497).then(n.bind(n,7325)),"@site/docs/customization.md",7325],fd1ae250:[()=>n.e(5221).then(n.bind(n,1458)),"@site/docs/trivy.md",1458]};function c(e){let{error:t,retry:n,pastDelay:a}=e;return t?r.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},r.createElement("p",null,String(t)),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},"Retry"))):a?r.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},r.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},r.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"8"},r.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(9670),d=n(226);function f(e,t){if("*"===e)return i()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return r.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},r.createElement(n,t))}});const o=s[e+"-"+t],f={},p=[],m=[],h=(0,u.Z)(o);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=l[n];r&&(f[t]=r[0],p.push(r[1]),m.push(r[2]))})),i().Map({loading:c,loader:f,modules:p,webpack:()=>m,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error("The page component at "+e+" doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.");"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let o=i;const s=n.split(".");s.slice(0,-1).forEach((e=>{o=o[e]})),o[s[s.length-1]]=a}));const s=i.__comp;delete i.__comp;const l=i.__context;return delete i.__context,r.createElement(d.z,{value:l},r.createElement(s,(0,a.Z)({},i,n)))}})}const p=[{path:"/eraser/docs/search",component:f("/eraser/docs/search","6c2"),exact:!0},{path:"/eraser/docs/next",component:f("/eraser/docs/next","3e9"),routes:[{path:"/eraser/docs/next",component:f("/eraser/docs/next","65e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/architecture",component:f("/eraser/docs/next/architecture","603"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/code-of-conduct",component:f("/eraser/docs/next/code-of-conduct","9c4"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/contributing",component:f("/eraser/docs/next/contributing","9d1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/custom-scanner",component:f("/eraser/docs/next/custom-scanner","ba1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/customization",component:f("/eraser/docs/next/customization","240"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/exclusion",component:f("/eraser/docs/next/exclusion","3b1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/faq",component:f("/eraser/docs/next/faq","764"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/installation",component:f("/eraser/docs/next/installation","fd3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/manual-removal",component:f("/eraser/docs/next/manual-removal","887"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/metrics",component:f("/eraser/docs/next/metrics","ca7"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/quick-start",component:f("/eraser/docs/next/quick-start","a1a"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/release-management",component:f("/eraser/docs/next/release-management","0b7"),exact:!0},{path:"/eraser/docs/next/releasing",component:f("/eraser/docs/next/releasing","bf4"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/setup",component:f("/eraser/docs/next/setup","fa3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/trivy",component:f("/eraser/docs/next/trivy","26a"),exact:!0,sidebar:"sidebar"}]},{path:"/eraser/docs/v0.4.x",component:f("/eraser/docs/v0.4.x","a77"),routes:[{path:"/eraser/docs/v0.4.x",component:f("/eraser/docs/v0.4.x","7f6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/architecture",component:f("/eraser/docs/v0.4.x/architecture","029"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/code-of-conduct",component:f("/eraser/docs/v0.4.x/code-of-conduct","7b8"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/contributing",component:f("/eraser/docs/v0.4.x/contributing","7d3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/custom-scanner",component:f("/eraser/docs/v0.4.x/custom-scanner","c20"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/customization",component:f("/eraser/docs/v0.4.x/customization","431"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/exclusion",component:f("/eraser/docs/v0.4.x/exclusion","1fa"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/faq",component:f("/eraser/docs/v0.4.x/faq","86f"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/installation",component:f("/eraser/docs/v0.4.x/installation","559"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/manual-removal",component:f("/eraser/docs/v0.4.x/manual-removal","1d0"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/quick-start",component:f("/eraser/docs/v0.4.x/quick-start","e66"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/releasing",component:f("/eraser/docs/v0.4.x/releasing","058"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/setup",component:f("/eraser/docs/v0.4.x/setup","223"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/trivy",component:f("/eraser/docs/v0.4.x/trivy","604"),exact:!0,sidebar:"sidebar"}]},{path:"/eraser/docs/v0.5.x",component:f("/eraser/docs/v0.5.x","574"),routes:[{path:"/eraser/docs/v0.5.x",component:f("/eraser/docs/v0.5.x","808"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/architecture",component:f("/eraser/docs/v0.5.x/architecture","1a5"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/code-of-conduct",component:f("/eraser/docs/v0.5.x/code-of-conduct","0e6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/contributing",component:f("/eraser/docs/v0.5.x/contributing","324"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/custom-scanner",component:f("/eraser/docs/v0.5.x/custom-scanner","3a5"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/customization",component:f("/eraser/docs/v0.5.x/customization","8f1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/exclusion",component:f("/eraser/docs/v0.5.x/exclusion","bee"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/faq",component:f("/eraser/docs/v0.5.x/faq","89b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/installation",component:f("/eraser/docs/v0.5.x/installation","a89"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/manual-removal",component:f("/eraser/docs/v0.5.x/manual-removal","e35"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/quick-start",component:f("/eraser/docs/v0.5.x/quick-start","6f3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/releasing",component:f("/eraser/docs/v0.5.x/releasing","c0e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/setup",component:f("/eraser/docs/v0.5.x/setup","df8"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/trivy",component:f("/eraser/docs/v0.5.x/trivy","2b4"),exact:!0,sidebar:"sidebar"}]},{path:"/eraser/docs/v1.0.x",component:f("/eraser/docs/v1.0.x","e8e"),routes:[{path:"/eraser/docs/v1.0.x",component:f("/eraser/docs/v1.0.x","c03"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/architecture",component:f("/eraser/docs/v1.0.x/architecture","0ac"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/code-of-conduct",component:f("/eraser/docs/v1.0.x/code-of-conduct","ef4"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/contributing",component:f("/eraser/docs/v1.0.x/contributing","e7d"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/custom-scanner",component:f("/eraser/docs/v1.0.x/custom-scanner","569"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/customization",component:f("/eraser/docs/v1.0.x/customization","85d"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/exclusion",component:f("/eraser/docs/v1.0.x/exclusion","3f0"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/faq",component:f("/eraser/docs/v1.0.x/faq","8ff"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/installation",component:f("/eraser/docs/v1.0.x/installation","688"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/manual-removal",component:f("/eraser/docs/v1.0.x/manual-removal","8a3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/metrics",component:f("/eraser/docs/v1.0.x/metrics","c54"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/quick-start",component:f("/eraser/docs/v1.0.x/quick-start","eed"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/releasing",component:f("/eraser/docs/v1.0.x/releasing","d7c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/setup",component:f("/eraser/docs/v1.0.x/setup","513"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/trivy",component:f("/eraser/docs/v1.0.x/trivy","5e8"),exact:!0,sidebar:"sidebar"}]},{path:"/eraser/docs/v1.1.x",component:f("/eraser/docs/v1.1.x","049"),routes:[{path:"/eraser/docs/v1.1.x",component:f("/eraser/docs/v1.1.x","f5e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/architecture",component:f("/eraser/docs/v1.1.x/architecture","211"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/code-of-conduct",component:f("/eraser/docs/v1.1.x/code-of-conduct","78b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/contributing",component:f("/eraser/docs/v1.1.x/contributing","1ae"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/custom-scanner",component:f("/eraser/docs/v1.1.x/custom-scanner","762"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/customization",component:f("/eraser/docs/v1.1.x/customization","9ba"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/exclusion",component:f("/eraser/docs/v1.1.x/exclusion","707"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/faq",component:f("/eraser/docs/v1.1.x/faq","e2c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/installation",component:f("/eraser/docs/v1.1.x/installation","a45"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/manual-removal",component:f("/eraser/docs/v1.1.x/manual-removal","1e9"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/metrics",component:f("/eraser/docs/v1.1.x/metrics","f2a"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/quick-start",component:f("/eraser/docs/v1.1.x/quick-start","9b5"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/releasing",component:f("/eraser/docs/v1.1.x/releasing","7ee"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/setup",component:f("/eraser/docs/v1.1.x/setup","ea6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/trivy",component:f("/eraser/docs/v1.1.x/trivy","fd6"),exact:!0,sidebar:"sidebar"}]},{path:"/eraser/docs/v1.2.x",component:f("/eraser/docs/v1.2.x","813"),routes:[{path:"/eraser/docs/v1.2.x",component:f("/eraser/docs/v1.2.x","a9e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/architecture",component:f("/eraser/docs/v1.2.x/architecture","45b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/code-of-conduct",component:f("/eraser/docs/v1.2.x/code-of-conduct","904"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/contributing",component:f("/eraser/docs/v1.2.x/contributing","80d"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/custom-scanner",component:f("/eraser/docs/v1.2.x/custom-scanner","fd2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/customization",component:f("/eraser/docs/v1.2.x/customization","a26"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/exclusion",component:f("/eraser/docs/v1.2.x/exclusion","a73"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/faq",component:f("/eraser/docs/v1.2.x/faq","c74"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/installation",component:f("/eraser/docs/v1.2.x/installation","005"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/manual-removal",component:f("/eraser/docs/v1.2.x/manual-removal","4e2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/metrics",component:f("/eraser/docs/v1.2.x/metrics","c26"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/quick-start",component:f("/eraser/docs/v1.2.x/quick-start","901"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/releasing",component:f("/eraser/docs/v1.2.x/releasing","e74"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/setup",component:f("/eraser/docs/v1.2.x/setup","62c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/trivy",component:f("/eraser/docs/v1.2.x/trivy","617"),exact:!0,sidebar:"sidebar"}]},{path:"/eraser/docs/",component:f("/eraser/docs/","e85"),routes:[{path:"/eraser/docs/",component:f("/eraser/docs/","5aa"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/architecture",component:f("/eraser/docs/architecture","cf6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/code-of-conduct",component:f("/eraser/docs/code-of-conduct","ad2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/contributing",component:f("/eraser/docs/contributing","b07"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/custom-scanner",component:f("/eraser/docs/custom-scanner","ffa"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/customization",component:f("/eraser/docs/customization","a79"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/exclusion",component:f("/eraser/docs/exclusion","62c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/faq",component:f("/eraser/docs/faq","630"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/installation",component:f("/eraser/docs/installation","a40"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/manual-removal",component:f("/eraser/docs/manual-removal","734"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/metrics",component:f("/eraser/docs/metrics","45e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/quick-start",component:f("/eraser/docs/quick-start","4ca"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/release-management",component:f("/eraser/docs/release-management","50e"),exact:!0},{path:"/eraser/docs/releasing",component:f("/eraser/docs/releasing","925"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/setup",component:f("/eraser/docs/setup","2c2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/trivy",component:f("/eraser/docs/trivy","86b"),exact:!0,sidebar:"sidebar"}]},{path:"*",component:f("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,t:()=>o});var r=n(7294);const a=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),r.createElement(a.Provider,{value:n},t)}},7221:(e,t,n)=>{"use strict";var r=n(7294),a=n(3935),o=n(3727),i=n(405),s=n(412);const l=[n(6657),n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6775),d=n(8790);function f(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var p=n(7462),m=n(5742),h=n(2263),g=n(4996),v=n(6668),b=n(833),y=n(4711),w=n(9727),x=n(3320),k=n(8780),E=n(197);function S(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,h.Z)(),n=(0,y.l)();return r.createElement(m.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:a}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:a})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function _(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),a=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.Z)(),{pathname:r}=(0,u.TH)();return e+(0,k.applyTrailingSlash)((0,g.Z)(r),{trailingSlash:n,baseUrl:t})}(),o=t?""+n+t:a;return r.createElement(m.Z,null,r.createElement("meta",{property:"og:url",content:o}),r.createElement("link",{rel:"canonical",href:o}))}function C(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,v.L)();return r.createElement(r.Fragment,null,r.createElement(m.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:w.h})),n&&r.createElement(b.d,{image:n}),r.createElement(_,null),r.createElement(S,null),r.createElement(E.Z,{tag:x.HX,locale:e}),r.createElement(m.Z,null,t.map(((e,t)=>r.createElement("meta",(0,p.Z)({key:t},e))))))}const T=new Map;function A(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var L=n(8934),R=n(8940);function N(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];const a=l.map((t=>{var r,a;const o=null!=(r=null==(a=t.default)?void 0:a[e])?r:t[e];return null==o?void 0:o(...n)}));return()=>a.forEach((e=>null==e?void 0:e()))}const P=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,r.useLayoutEffect)((()=>{a!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);null==t||t.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:a}),N("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>null==e.route.component.preload?void 0:e.route.component.preload())))}class I extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?N("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=N("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return r.createElement(P,{previousLocation:this.previousLocation,location:t},r.createElement(u.AW,{location:t,render:()=>e}))}}const D=I,M="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner-suggestion-container",B="__DOCUSAURUS_INSERT_BASEURL_BANNER";function j(e){return"\nwindow['"+B+"'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['"+B+"'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('"+M+"');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = "+JSON.stringify(function(e){return'\n<div id="__docusaurus-base-url-issue-banner" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">'+e+"</span> "+("/"===e?" (default value)":"")+'</p>\n <p>We suggest trying baseUrl = <span id="'+F+'" style="font-weight: bold; color: green;"></span></p>\n</div>\n'}(e)).replace(/</g,"\\<")+";\n bannerContainer.innerHTML = bannerHtml;\n var suggestionContainer = document.getElementById('"+F+"');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n"}function z(){const{siteConfig:{baseUrl:e}}=(0,h.Z)();return(0,r.useLayoutEffect)((()=>{window[B]=!1}),[]),r.createElement(r.Fragment,null,!s.Z.canUseDOM&&r.createElement(m.Z,null,r.createElement("script",null,j(e))),r.createElement("div",{id:M}))}function U(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?r.createElement(z,null):null}function q(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:a,localeConfigs:o}}=(0,h.Z)(),i=(0,g.Z)(e),{htmlLang:s,direction:l}=o[a];return r.createElement(m.Z,null,r.createElement("html",{lang:s,dir:l}),r.createElement("title",null,t),r.createElement("meta",{property:"og:title",content:t}),r.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&r.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&r.createElement("link",{rel:"icon",href:i}))}var $=n(4763),H=n(2389);function G(){const e=(0,H.Z)();return r.createElement(m.Z,null,r.createElement("html",{"data-has-hydrated":e}))}function Z(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return r.createElement($.Z,null,r.createElement(R.M,null,r.createElement(L.t,null,r.createElement(f,null,r.createElement(q,null),r.createElement(C,null),r.createElement(U,null),r.createElement(D,{location:A(t)},e)),r.createElement(G,null))))}var V=n(6887);const W=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{var r,a;if("undefined"==typeof document)return void n();const o=document.createElement("link");o.setAttribute("rel","prefetch"),o.setAttribute("href",e),o.onload=()=>t(),o.onerror=()=>n();const i=null!=(r=document.getElementsByTagName("head")[0])?r:null==(a=document.getElementsByName("script")[0])?void 0:a.parentNode;null==i||i.appendChild(o)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var K=n(9670);const Y=new Set,Q=new Set,X=()=>{var e,t;return(null==(e=navigator.connection)?void 0:e.effectiveType.includes("2g"))||(null==(t=navigator.connection)?void 0:t.saveData)},J={prefetch(e){if(!(e=>!X()&&!Q.has(e)&&!Y.has(e))(e))return!1;Y.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(V).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,K.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?W(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!X()&&!Q.has(e))(e)&&(Q.add(e),O(e))},ee=Object.freeze(J);if(s.Z.canUseDOM){window.docusaurus=ee;const e=a.hydrate;O(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(o.VK,null,r.createElement(Z,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-QV5PNCJ560"],"anonymizeIP":true,"id":"default"}},"docusaurus-plugin-content-docs":{"default":{"path":"/eraser/docs/","versions":[{"name":"current","label":"Next","isLast":false,"path":"/eraser/docs/next","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/next/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/next/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/next/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/next/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/next/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/next/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/next/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/next/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/next/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/next/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/next/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/next/quick-start","sidebar":"sidebar"},{"id":"release-management","path":"/eraser/docs/next/release-management"},{"id":"releasing","path":"/eraser/docs/next/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/next/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/next/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/next/","label":"introduction"}}}},{"name":"v1.3.x","label":"v1.3.x","isLast":true,"path":"/eraser/docs/","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/quick-start","sidebar":"sidebar"},{"id":"release-management","path":"/eraser/docs/release-management"},{"id":"releasing","path":"/eraser/docs/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/","label":"introduction"}}}},{"name":"v1.2.x","label":"v1.2.x","isLast":false,"path":"/eraser/docs/v1.2.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v1.2.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v1.2.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v1.2.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v1.2.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v1.2.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v1.2.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v1.2.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v1.2.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v1.2.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v1.2.x/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/v1.2.x/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v1.2.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v1.2.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v1.2.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v1.2.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v1.2.x/","label":"introduction"}}}},{"name":"v1.1.x","label":"v1.1.x","isLast":false,"path":"/eraser/docs/v1.1.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v1.1.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v1.1.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v1.1.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v1.1.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v1.1.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v1.1.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v1.1.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v1.1.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v1.1.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v1.1.x/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/v1.1.x/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v1.1.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v1.1.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v1.1.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v1.1.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v1.1.x/","label":"introduction"}}}},{"name":"v1.0.x","label":"v1.0.x","isLast":false,"path":"/eraser/docs/v1.0.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v1.0.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v1.0.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v1.0.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v1.0.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v1.0.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v1.0.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v1.0.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v1.0.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v1.0.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v1.0.x/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/v1.0.x/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v1.0.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v1.0.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v1.0.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v1.0.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v1.0.x/","label":"introduction"}}}},{"name":"v0.5.x","label":"v0.5.x","isLast":false,"path":"/eraser/docs/v0.5.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v0.5.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v0.5.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v0.5.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v0.5.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v0.5.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v0.5.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v0.5.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v0.5.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v0.5.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v0.5.x/manual-removal","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v0.5.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v0.5.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v0.5.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v0.5.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v0.5.x/","label":"introduction"}}}},{"name":"v0.4.x","label":"v0.4.x","isLast":false,"path":"/eraser/docs/v0.4.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v0.4.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v0.4.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v0.4.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v0.4.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v0.4.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v0.4.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v0.4.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v0.4.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v0.4.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v0.4.x/manual-removal","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v0.4.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v0.4.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v0.4.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v0.4.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v0.4.x/","label":"introduction"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(7529);const l=JSON.parse('{"docusaurusVersion":"2.4.3","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.4.3"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.4.3"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"2.4.3"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.4.3"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.4.3"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"2.4.3"}}}'),c={siteConfig:a.Z,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},u=r.createContext(c);function d(e){let{children:t}=e;return r.createElement(u.Provider,{value:c},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(412),o=n(5742),i=n(8780),s=n(7452);function l(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"}},r.createElement("h1",{style:{fontSize:"3rem"}},"This page crashed"),r.createElement("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"}},"Try again"),r.createElement(c,{error:t}))}function c(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{style:{whiteSpace:"pre-wrap"}},n)}function u(e){let{error:t,tryAgain:n}=e;return r.createElement(f,{fallback:()=>r.createElement(l,{error:t,tryAgain:n})},r.createElement(o.Z,null,r.createElement("title",null,"Page Error")),r.createElement(s.Z,null,r.createElement(l,{error:t,tryAgain:n})))}const d=e=>r.createElement(u,e);class f extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){var n;const e={error:t,tryAgain:()=>this.setState({error:null})};return(null!=(n=this.props.fallback)?n:d)(e)}return null!=e?e:null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(405);function o(e){return r.createElement(a.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7462),a=n(7294),o=n(3727),i=n(8780),s=n(2263),l=n(3919),c=n(412);const u=a.createContext({collectLink:()=>{}});var d=n(4996);function f(e,t){var n,f;let{isNavLink:p,to:m,href:h,activeClassName:g,isActive:v,"data-noBrokenLinkCheck":b,autoAddBaseUrl:y=!0,...w}=e;const{siteConfig:{trailingSlash:x,baseUrl:k}}=(0,s.Z)(),{withBaseUrl:E}=(0,d.C)(),S=(0,a.useContext)(u),_=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>_.current));const C=m||h;const T=(0,l.Z)(C),A=null==C?void 0:C.replace("pathname://","");let L=void 0!==A?(R=A,y&&(e=>e.startsWith("/"))(R)?E(R):R):void 0;var R;L&&T&&(L=(0,i.applyTrailingSlash)(L,{trailingSlash:x,baseUrl:k}));const N=(0,a.useRef)(!1),P=p?o.OL:o.rU,O=c.Z.canUseIntersectionObserver,I=(0,a.useRef)(),D=()=>{N.current||null==L||(window.docusaurus.preload(L),N.current=!0)};(0,a.useEffect)((()=>(!O&&T&&null!=L&&window.docusaurus.prefetch(L),()=>{O&&I.current&&I.current.disconnect()})),[I,L,O,T]);const M=null!=(n=null==(f=L)?void 0:f.startsWith("#"))&&n,F=!L||!T||M;return F||b||S.collectLink(L),F?a.createElement("a",(0,r.Z)({ref:_,href:L},C&&!T&&{target:"_blank",rel:"noopener noreferrer"},w)):a.createElement(P,(0,r.Z)({},w,{onMouseEnter:D,onTouchStart:D,innerRef:e=>{_.current=e,O&&e&&T&&(I.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(I.current.unobserve(e),I.current.disconnect(),null!=L&&window.docusaurus.prefetch(L))}))})),I.current.observe(e))},to:L},p&&{isActive:v,activeClassName:g}))}const p=a.forwardRef(f)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>s});var r=n(7294);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=null==t?void 0:t[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function i(e){var t,n;let{id:r,message:a}=e;if(void 0===r&&void 0===a)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return null!=(t=null!=(n=o[null!=r?r:a])?n:a)?t:r}function s(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const s=i({message:t,id:n});return r.createElement(r.Fragment,null,a(s,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var r=n(7294),a=n(2263),o=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,a.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:a=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(a)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[a,o]=n;const i=r?r+"."+a:a;var s;"object"==typeof(s=o)&&s&&Object.keys(s).length>0?e(o,i):t[i]=o}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,z:()=>o});var r=n(7294);const a=r.createContext(null);function o(e){let{children:t,value:n}=e;const o=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...null==n?void 0:n.data};return{plugin:t.plugin,data:r}}({parent:o,value:n})),[o,n]);return r.createElement(a.Provider,{value:i},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>v,gA:()=>p,WS:()=>m,_r:()=>d,Jo:()=>b,zh:()=>f,yW:()=>g,gB:()=>h});var r=n(6775),a=n(2263),o=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,a.Z)();return e}()[e];if(!n&&t.failfast)throw new Error('Docusaurus plugin global data not found for "'+e+'" plugin.');return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}function c(e,t){const n=l(e,t),a=null==n?void 0:n.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const u={},d=()=>{var e;return null!=(e=i("docusaurus-plugin-content-docs"))?e:u},f=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const r=i(e),a=null==r?void 0:r[t];if(!a&&n.failfast)throw new Error('Docusaurus plugin global data not found for "'+e+'" plugin with id "'+t+'".');return a}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error("Can't find active docs plugin for \""+t+'" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: '+Object.values(e).map((e=>e.path)).join(", "));return o}(t,n,e)}function m(e){void 0===e&&(e={});const t=p(e),{pathname:n}=(0,r.TH)();if(!t)return;return{activePlugin:t,activeVersion:l(t.pluginData,n)}}function h(e){return f(e).versions}function g(e){const t=f(e);return s(t)}function v(e){const t=f(e),{pathname:n}=(0,r.TH)();return c(t,n)}function b(e){const t=f(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:c(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},6657:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("event","page_view",{page_title:document.title,page_location:window.location.href,page_path:t.pathname+t.search+t.hash})}))}}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(1205),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.Z,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{n(6726)("./prism-"+e)})),delete globalThis.Prism}(r.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294);const a="iconExternalLink_nPIU";function o(e){let{width:t=13.5,height:n=13.5}=e;return r.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a},r.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},7452:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Ot});var r=n(7294),a=n(4334),o=n(4763),i=n(833),s=n(7462),l=n(6775),c=n(5999),u=n(5936);const d="__docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,r.useRef)(null),{action:t}=(0,l.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=null!=(n=document.querySelector("main:first-of-type"))?n:document.getElementById(d);var n;t&&f(t)}),[]);return(0,u.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){var t;const n=null!=(t=e.children)?t:m,{containerRef:a,onClick:o}=p();return r.createElement("div",{ref:a,role:"region","aria-label":m},r.createElement("a",(0,s.Z)({},e,{href:"#"+d,onClick:o}),n))}var g=n(5281),v=n(9727);const b="skipToContent_fXgn";function y(){return r.createElement(h,{className:b})}var w=n(6668),x=n(9689);function k(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...l}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 15 15",width:t,height:n},l),r.createElement("g",{stroke:a,strokeWidth:o},r.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const E="closeButton_CVFx";function S(e){return r.createElement("button",(0,s.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,a.Z)("clean-btn close",E,e.className)}),r.createElement(k,{width:14,height:14,strokeWidth:3.1}))}const _="content_knG7";function C(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return r.createElement("div",(0,s.Z)({},e,{className:(0,a.Z)(_,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T="announcementBar_mb4j",A="announcementBarPlaceholder_vyr4",L="announcementBarClose_gvF7",R="announcementBarContent_xLdY";function N(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,x.nT)();if(!t)return null;const{backgroundColor:a,textColor:o,isCloseable:i}=e;return r.createElement("div",{className:T,style:{backgroundColor:a,color:o},role:"banner"},i&&r.createElement("div",{className:A}),r.createElement(C,{className:R}),i&&r.createElement(S,{onClick:n,className:L}))}var P=n(3163),O=n(2466);var I=n(902),D=n(3102);const M=r.createContext(null);function F(e){let{children:t}=e;const n=function(){const e=(0,P.e)(),t=(0,D.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,I.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return r.createElement(M.Provider,{value:n},t)}function B(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function j(){const e=(0,r.useContext)(M);if(!e)throw new I.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,D.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:B(o)})),[a,o,t])}function z(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=j();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},r.createElement("div",{className:"navbar-sidebar__item menu"},n),r.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var U=n(2949),q=n(2389);function $(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function H(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const G={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function Z(e){let{className:t,buttonClassName:n,value:o,onChange:i}=e;const s=(0,q.Z)(),l=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===o?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return r.createElement("div",{className:(0,a.Z)(G.toggle,t)},r.createElement("button",{className:(0,a.Z)("clean-btn",G.toggleButton,!s&&G.toggleButtonDisabled,n),type:"button",onClick:()=>i("dark"===o?"light":"dark"),disabled:!s,title:l,"aria-label":l,"aria-live":"polite"},r.createElement($,{className:(0,a.Z)(G.toggleIcon,G.lightToggleIcon)}),r.createElement(H,{className:(0,a.Z)(G.toggleIcon,G.darkToggleIcon)})))}const V=r.memo(Z),W="darkNavbarColorModeToggle_X3D1";function K(e){let{className:t}=e;const n=(0,w.L)().navbar.style,a=(0,w.L)().colorMode.disableSwitch,{colorMode:o,setColorMode:i}=(0,U.I)();return a?null:r.createElement(V,{className:t,buttonClassName:"dark"===n?W:void 0,value:o,onChange:i})}var Y=n(1327);function Q(){return r.createElement(Y.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function X(){const e=(0,P.e)();return r.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},r.createElement(k,{color:"var(--ifm-color-emphasis-600)"}))}function J(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(Q,null),r.createElement(K,{className:"margin-right--md"}),r.createElement(X,null))}var ee=n(9960),te=n(4996),ne=n(3919),re=n(8022),ae=n(9471);function oe(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const f=(0,te.Z)(a),p=(0,te.Z)(t),m=(0,te.Z)(o,{forcePrependBaseUrl:!0}),h=i&&o&&!(0,ne.Z)(o),g=l?{dangerouslySetInnerHTML:{__html:l}}:{children:r.createElement(r.Fragment,null,i,h&&r.createElement(ae.Z,c&&{width:12,height:12}))};return o?r.createElement(ee.Z,(0,s.Z)({href:u?m:o},d,g)):r.createElement(ee.Z,(0,s.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?(0,re.F)(n,t.pathname):t.pathname.startsWith(p)},d,g))}function ie(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=r.createElement(oe,(0,s.Z)({className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?r.createElement("li",null,i):i}function se(e){let{className:t,isDropdownItem:n,...o}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(oe,(0,s.Z)({className:(0,a.Z)("menu__link",t)},o)))}function le(e){var t;let{mobile:n=!1,position:a,...o}=e;const i=n?se:ie;return r.createElement(i,(0,s.Z)({},o,{activeClassName:null!=(t=o.activeClassName)?t:n?"menu__link--active":"navbar__link--active"}))}var ce=n(6043),ue=n(8596),de=n(2263);function fe(e,t){return e.some((e=>function(e,t){return!!(0,ue.Mg)(e.to,t)||!!(0,re.F)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function pe(e){var t;let{items:n,position:o,className:i,onClick:l,...c}=e;const u=(0,r.useRef)(null),[d,f]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{u.current&&!u.current.contains(e.target)&&f(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[u]),r.createElement("div",{ref:u,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===o,"dropdown--show":d})},r.createElement(oe,(0,s.Z)({"aria-haspopup":"true","aria-expanded":d,role:"button",href:c.to?void 0:"#",className:(0,a.Z)("navbar__link",i)},c,{onClick:c.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),f(!d))}}),null!=(t=c.children)?t:c.label),r.createElement("ul",{className:"dropdown__menu"},n.map(((e,t)=>r.createElement(Ze,(0,s.Z)({isDropdownItem:!0,activeClassName:"dropdown__link--active"},e,{key:t}))))))}function me(e){var t;let{items:n,className:o,position:i,onClick:c,...u}=e;const d=function(){const{siteConfig:{baseUrl:e}}=(0,de.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),f=fe(n,d),{collapsed:p,toggleCollapsed:m,setCollapsed:h}=(0,ce.u)({initialState:()=>!f});return(0,r.useEffect)((()=>{f&&h(!f)}),[d,f,h]),r.createElement("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":p})},r.createElement(oe,(0,s.Z)({role:"button",className:(0,a.Z)("menu__link menu__link--sublist menu__link--sublist-caret",o)},u,{onClick:e=>{e.preventDefault(),m()}}),null!=(t=u.children)?t:u.label),r.createElement(ce.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p},n.map(((e,t)=>r.createElement(Ze,(0,s.Z)({mobile:!0,isDropdownItem:!0,onClick:c,activeClassName:"menu__link--active"},e,{key:t}))))))}function he(e){let{mobile:t=!1,...n}=e;const a=t?me:pe;return r.createElement(a,n)}var ge=n(4711);function ve(e){let{width:t=20,height:n=20,...a}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},a),r.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const be="iconLanguage_nlXk";function ye(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var we=n(830),xe=["translations"];function ke(){return ke=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},ke.apply(this,arguments)}function Ee(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==n)return;var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(l){s=!0,a=l}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return Se(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Se(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Se(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function _e(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var Ce="Ctrl";var Te=r.forwardRef((function(e,t){var n=e.translations,a=void 0===n?{}:n,o=_e(e,xe),i=a.buttonText,s=void 0===i?"Search":i,l=a.buttonAriaLabel,c=void 0===l?"Search":l,u=Ee((0,r.useState)(null),2),d=u[0],f=u[1];return(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?f("\u2318"):f(Ce))}),[]),r.createElement("button",ke({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(we.W,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&r.createElement(r.Fragment,null,r.createElement("kbd",{className:"DocSearch-Button-Key"},d===Ce?r.createElement(ye,null):d),r.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Ae=n(5742),Le=n(6177),Re=n(239),Ne=n(3320);var Pe=n(3935);const Oe={button:{buttonText:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.I)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.I)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.I)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.I)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.I)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.I)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.I)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.I)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Ie=null;function De(e){let{hit:t,children:n}=e;return r.createElement(ee.Z,{to:t.url},n)}function Me(e){let{state:t,onClose:n}=e;const a=(0,Le.M)();return r.createElement(ee.Z,{to:a(t.query),onClick:n},r.createElement(c.Z,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits}},"See all {count} results"))}function Fe(e){var t,a;let{contextualSearch:o,externalUrlRegex:i,...c}=e;const{siteMetadata:u}=(0,de.Z)(),d=(0,Re.l)(),f=function(){const{locale:e,tags:t}=(0,Ne._q)();return["language:"+e,t.map((e=>"docusaurus_tag:"+e))]}(),p=null!=(t=null==(a=c.searchParameters)?void 0:a.facetFilters)?t:[],m=o?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(f,p):p,h={...c.searchParameters,facetFilters:m},g=(0,l.k6)(),v=(0,r.useRef)(null),b=(0,r.useRef)(null),[y,w]=(0,r.useState)(!1),[x,k]=(0,r.useState)(void 0),E=(0,r.useCallback)((()=>Ie?Promise.resolve():Promise.all([n.e(6780).then(n.bind(n,6780)),Promise.all([n.e(532),n.e(6945)]).then(n.bind(n,6945)),Promise.all([n.e(532),n.e(8894)]).then(n.bind(n,8894))]).then((e=>{let[{DocSearchModal:t}]=e;Ie=t}))),[]),S=(0,r.useCallback)((()=>{E().then((()=>{v.current=document.createElement("div"),document.body.insertBefore(v.current,document.body.firstChild),w(!0)}))}),[E,w]),_=(0,r.useCallback)((()=>{var e;w(!1),null==(e=v.current)||e.remove()}),[w]),C=(0,r.useCallback)((e=>{E().then((()=>{w(!0),k(e.key)}))}),[E,w,k]),T=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,re.F)(i,t)?window.location.href=t:g.push(t)}}).current,A=(0,r.useRef)((e=>c.transformItems?c.transformItems(e):e.map((e=>({...e,url:d(e.url)}))))).current,L=(0,r.useMemo)((()=>e=>r.createElement(Me,(0,s.Z)({},e,{onClose:_}))),[_]),R=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",u.docusaurusVersion),e)),[u.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,a=e.onClose,o=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){(27===e.keyCode&&t||"k"===e.key&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?a():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&o&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&o(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,a,o,i])}({isOpen:y,onOpen:S,onClose:_,onInput:C,searchButtonRef:b}),r.createElement(r.Fragment,null,r.createElement(Ae.Z,null,r.createElement("link",{rel:"preconnect",href:"https://"+c.appId+"-dsn.algolia.net",crossOrigin:"anonymous"})),r.createElement(Te,{onTouchStart:E,onFocus:E,onMouseOver:E,onClick:S,ref:b,translations:Oe.button}),y&&Ie&&v.current&&(0,Pe.createPortal)(r.createElement(Ie,(0,s.Z)({onClose:_,initialScrollY:window.scrollY,initialQuery:x,navigator:T,transformItems:A,hitComponent:De,transformSearchClient:R},c.searchPagePath&&{resultsFooterComponent:L},c,{searchParameters:h,placeholder:Oe.placeholder,translations:Oe.modal})),v.current))}function Be(){const{siteConfig:e}=(0,de.Z)();return r.createElement(Fe,e.themeConfig.algolia)}const je="searchBox_ZlJk";function ze(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,a.Z)(n,je)},t)}var Ue=n(143),qe=n(2802);var $e=n(373);const He=e=>e.docs.find((t=>t.id===e.mainDocId));const Ge={default:le,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,...o}=e;const{i18n:{currentLocale:i,locales:u,localeConfigs:d}}=(0,de.Z)(),f=(0,ge.l)(),{search:p,hash:m}=(0,l.TH)(),h=[...n,...u.map((e=>{const n=""+("pathname://"+f.createUrl({locale:e,fullyQualified:!1}))+p+m;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],g=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return r.createElement(he,(0,s.Z)({},o,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(ve,{className:be}),g),items:h}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement(ze,{className:n},r.createElement(Be,null))},dropdown:he,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const s=i?"li":"div";return r.createElement(s,{className:(0,a.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,Ue.Iw)(a),l=(0,qe.vY)(t,a);return null===l?null:r.createElement(le,(0,s.Z)({exact:!0},o,{isActive:()=>(null==i?void 0:i.path)===l.path||!(null==i||!i.sidebar)&&i.sidebar===l.sidebar,label:null!=n?n:l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,Ue.Iw)(a),l=(0,qe.oz)(t,a).link;if(!l)throw new Error('DocSidebarNavbarItem: Sidebar with ID "'+t+"\" doesn't have anything to be linked to.");return r.createElement(le,(0,s.Z)({exact:!0},o,{isActive:()=>(null==i?void 0:i.sidebar)===t,label:null!=n?n:l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e;const i=(0,qe.lO)(a)[0],l=null!=t?t:i.label,c=null!=n?n:(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return r.createElement(le,(0,s.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...u}=e;const{search:d,hash:f}=(0,l.TH)(),p=(0,Ue.Iw)(n),m=(0,Ue.gB)(n),{savePreferredVersionName:h}=(0,$e.J)(n),g=[...o,...m.map((e=>{var t;const n=null!=(t=p.alternateDocVersions[e.name])?t:He(e);return{label:e.label,to:""+n.path+d+f,isActive:()=>e===p.activeVersion,onClick:()=>h(e.name)}})),...i],v=(0,qe.lO)(n)[0],b=t&&g.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):v.label,y=t&&g.length>1?void 0:He(v).path;return g.length<=1?r.createElement(le,(0,s.Z)({},u,{mobile:t,label:b,to:y,isActive:a?()=>!1:void 0})):r.createElement(he,(0,s.Z)({},u,{mobile:t,label:b,to:y,items:g,isActive:a?()=>!1:void 0}))}};function Ze(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ge[a];if(!o)throw new Error('No NavbarItem component found for type "'+t+'".');return r.createElement(o,n)}function Ve(){const e=(0,P.e)(),t=(0,w.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(Ze,(0,s.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function We(e){return r.createElement("button",(0,s.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),r.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function Ke(){const e=0===(0,w.L)().navbar.items.length,t=j();return r.createElement(r.Fragment,null,!e&&r.createElement(We,{onClick:()=>t.hide()}),t.content)}function Ye(){const e=(0,P.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?r.createElement(z,{header:r.createElement(J,null),primaryMenu:r.createElement(Ve,null),secondaryMenu:r.createElement(Ke,null)}):null}const Qe="navbarHideable_m1mJ",Xe="navbarHidden_jGov";function Je(e){return r.createElement("div",(0,s.Z)({role:"presentation"},e,{className:(0,a.Z)("navbar-sidebar__backdrop",e.className)}))}function et(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,P.e)(),{navbarRef:s,isNavbarVisible:l}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,O.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i<o.current)return void n(!0);if(a.current)return void(a.current=!1);const s=null==r?void 0:r.scrollY,l=document.documentElement.scrollHeight-o.current,c=window.innerHeight;s&&i>=s?n(!1):i+c<l&&n(!0)})),(0,u.S)((t=>{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return r.createElement("nav",{ref:s,"aria-label":(0,c.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Qe,!l&&Xe],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,r.createElement(Je,{onClick:i.toggle}),r.createElement(Ye,null))}var tt=n(8780);const nt="errorBoundaryError_a6uf";function rt(e){return r.createElement("button",(0,s.Z)({type:"button"},e),r.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error"},"Try again"))}function at(e){let{error:t}=e;const n=(0,tt.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{className:nt},n)}class ot extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}function it(e){let{width:t=30,height:n=30,className:a,...o}=e;return r.createElement("svg",(0,s.Z)({className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function st(){const{toggle:e,shown:t}=(0,P.e)();return r.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},r.createElement(it,null))}const lt="colorModeToggle_DEke";function ct(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(ot,{key:t,onError:t=>new Error("A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n"+JSON.stringify(e,null,2),{cause:t})},r.createElement(Ze,e)))))}function ut(e){let{left:t,right:n}=e;return r.createElement("div",{className:"navbar__inner"},r.createElement("div",{className:"navbar__items"},t),r.createElement("div",{className:"navbar__items navbar__items--right"},n))}function dt(){const e=(0,P.e)(),t=(0,w.L)().navbar.items,[n,a]=function(e){function t(e){var t;return"left"===(null!=(t=e.position)?t:"right")}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return r.createElement(ut,{left:r.createElement(r.Fragment,null,!e.disabled&&r.createElement(st,null),r.createElement(Q,null),r.createElement(ct,{items:n})),right:r.createElement(r.Fragment,null,r.createElement(ct,{items:a}),r.createElement(K,{className:lt}),!o&&r.createElement(ze,null,r.createElement(Be,null)))})}function ft(){return r.createElement(et,null,r.createElement(dt,null))}function pt(e){let{item:t}=e;const{to:n,href:a,label:o,prependBaseUrlToHref:i,...l}=t,c=(0,te.Z)(n),u=(0,te.Z)(a,{forcePrependBaseUrl:!0});return r.createElement(ee.Z,(0,s.Z)({className:"footer__link-item"},a?{href:i?u:a}:{to:c},l),o,a&&!(0,ne.Z)(a)&&r.createElement(ae.Z,null))}function mt(e){var t;let{item:n}=e;return n.html?r.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:n.html}}):r.createElement("li",{key:null!=(t=n.href)?t:n.to,className:"footer__item"},r.createElement(pt,{item:n}))}function ht(e){let{column:t}=e;return r.createElement("div",{className:"col footer__col"},r.createElement("div",{className:"footer__title"},t.title),r.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>r.createElement(mt,{key:t,item:e})))))}function gt(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(ht,{key:t,column:e}))))}function vt(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function bt(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement(pt,{item:t})}function yt(e){let{links:t}=e;return r.createElement("div",{className:"footer__links text--center"},r.createElement("div",{className:"footer__links"},t.map(((e,n)=>r.createElement(r.Fragment,{key:n},r.createElement(bt,{item:e}),t.length!==n+1&&r.createElement(vt,null))))))}function wt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(gt,{columns:t}):r.createElement(yt,{links:t})}var xt=n(941);const kt="footerLogoLink_BH7S";function Et(e){var t;let{logo:n}=e;const{withBaseUrl:o}=(0,te.C)(),i={light:o(n.src),dark:o(null!=(t=n.srcDark)?t:n.src)};return r.createElement(xt.Z,{className:(0,a.Z)("footer__logo",n.className),alt:n.alt,sources:i,width:n.width,height:n.height,style:n.style})}function St(e){let{logo:t}=e;return t.href?r.createElement(ee.Z,{href:t.href,className:kt,target:t.target},r.createElement(Et,{logo:t})):r.createElement(Et,{logo:t})}function _t(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function Ct(e){let{style:t,links:n,logo:o,copyright:i}=e;return r.createElement("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(o||i)&&r.createElement("div",{className:"footer__bottom text--center"},o&&r.createElement("div",{className:"margin-bottom--sm"},o),i)))}function Tt(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:o}=e;return r.createElement(Ct,{style:o,links:n&&n.length>0&&r.createElement(wt,{links:n}),logo:a&&r.createElement(St,{logo:a}),copyright:t&&r.createElement(_t,{copyright:t})})}const At=r.memo(Tt),Lt=(0,I.Qc)([U.S,x.pl,O.OC,$e.L5,i.VC,function(e){let{children:t}=e;return r.createElement(D.n2,null,r.createElement(P.M,null,r.createElement(F,null,t)))}]);function Rt(e){let{children:t}=e;return r.createElement(Lt,null,t)}function Nt(e){let{error:t,tryAgain:n}=e;return r.createElement("main",{className:"container margin-vert--xl"},r.createElement("div",{className:"row"},r.createElement("div",{className:"col col--6 col--offset-3"},r.createElement("h1",{className:"hero__title"},r.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),r.createElement("div",{className:"margin-vert--lg"},r.createElement(rt,{onClick:n,className:"button button--primary shadow--lw"})),r.createElement("hr",null),r.createElement("div",{className:"margin-vert--md"},r.createElement(at,{error:t})))))}const Pt="mainWrapper_z2l0";function Ot(e){const{children:t,noFooter:n,wrapperClassName:s,title:l,description:c}=e;return(0,v.t)(),r.createElement(Rt,null,r.createElement(i.d,{title:l,description:c}),r.createElement(y,null),r.createElement(N,null),r.createElement(ft,null),r.createElement("div",{id:d,className:(0,a.Z)(g.k.wrapper.main,Pt,s)},r.createElement(o.Z,{fallback:e=>r.createElement(Nt,e)},t)),!n&&r.createElement(At,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),a=n(7294),o=n(9960),i=n(4996),s=n(2263),l=n(6668),c=n(941);function u(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},s=a.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?a.createElement("div",{className:r},s):s}function d(e){var t;const{siteConfig:{title:n}}=(0,s.Z)(),{navbar:{title:c,logo:d}}=(0,l.L)(),{imageClassName:f,titleClassName:p,...m}=e,h=(0,i.Z)((null==d?void 0:d.href)||"/"),g=c?"":n,v=null!=(t=null==d?void 0:d.alt)?t:g;return a.createElement(o.Z,(0,r.Z)({to:h},m,(null==d?void 0:d.target)&&{target:d.target}),d&&a.createElement(u,{logo:d,alt:v,imageClassName:f}),null!=c&&a.createElement("b",{className:p},c))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return r.createElement(a.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),o&&r.createElement("meta",{name:"docusaurus_tag",content:o}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),o&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var r=n(7462),a=n(7294),o=n(4334),i=n(2389),s=n(2949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,i.Z)(),{colorMode:n}=(0,s.I)(),{sources:c,className:u,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return a.createElement(a.Fragment,null,p.map((e=>a.createElement("img",(0,r.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l["themedImage--"+e],u)},f)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>s,z:()=>h});var r=n(7462),a=n(7294),o=n(412),i=n(1442);function s(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(null!=t&&t),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const l={display:"none",overflow:"hidden",height:"0px"},c={display:"block",overflow:"visible",height:"auto"};function u(e,t){const n=t?l:c;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function d(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){var t,n;const a=e.scrollHeight,o=null!=(t=null==r?void 0:r.duration)?t:function(e){if((0,i.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(a);return{transition:"height "+o+"ms "+(null!=(n=null==r?void 0:r.easing)?n:"ease-in-out"),height:a+"px"}}function s(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return u(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=l.height,e.style.overflow=l.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function f(e){if(!o.Z.canUseDOM)return e?l:c}function p(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:s,disableSSRStyle:l}=e;const c=(0,a.useRef)(null);return d({collapsibleRef:c,collapsed:n,animation:o}),a.createElement(t,{ref:c,style:l?void 0:f(n),onTransitionEnd:e=>{"height"===e.propertyName&&(u(c.current,n),null==i||i(n))},className:s},r)}function m(e){let{collapsed:t,...n}=e;const[o,i]=(0,a.useState)(!t),[s,l]=(0,a.useState)(t);return(0,a.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,a.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?a.createElement(p,(0,r.Z)({},n,{collapsed:s})):null}function h(e){let{lazy:t,...n}=e;const r=t?m:p;return a.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>m,pl:()=>p});var r=n(7294),a=n(2389),o=n(12),i=n(902),s=n(6668);const l=(0,o.WA)("docusaurus.announcement.dismiss"),c=(0,o.WA)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),f=r.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&u()));(0,r.useEffect)((()=>{o(u())}),[]);const i=(0,r.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;c.set(t),r&&d(!1),!r&&u()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(f.Provider,{value:n},t)}function m(){const e=(0,r.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>g,S:()=>h});var r=n(7294),a=n(412),o=n(902),i=n(12),s=n(6668);const l=r.createContext(void 0),c="theme",u=(0,i.WA)(c),d="light",f="dark",p=e=>e===f?f:d;function m(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[o,i]=(0,r.useState)((e=>a.Z.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e))(e));(0,r.useEffect)((()=>{t&&u.del()}),[t]);const l=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(i(t),a&&(e=>{u.set(p(e))})(t)):(i(n?window.matchMedia("(prefers-color-scheme: dark)").matches?f:d:e),u.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",p(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&l(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,l]);const m=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||m.current?m.current=window.matchMedia("print").matches:l(null)};return e.addListener(r),()=>e.removeListener(r)}),[l,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:l,get isDarkTheme(){return o===f},setLightTheme(){l(d)},setDarkTheme(){l(f)}})),[o,l])}function h(e){let{children:t}=e;const n=m();return r.createElement(l.Provider,{value:n},t)}function g(){const e=(0,r.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>y,L5:()=>v,Oh:()=>w});var r=n(7294),a=n(143),o=n(9935),i=n(6668),s=n(2802),l=n(902),c=n(12);const u=e=>"docs-preferred-version-"+e,d=(e,t,n)=>{(0,c.WA)(u(e),{persistence:t}).set(n)},f=(e,t)=>(0,c.WA)(u(e),{persistence:t}).get(),p=(e,t)=>{(0,c.WA)(u(e),{persistence:t}).del()};const m=r.createContext(null);function h(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,r.useState)((()=>(e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}]))))(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=f(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=h();return r.createElement(m.Provider,{value:n},t)}function v(e){let{children:t}=e;return s.cE?r.createElement(g,null,t):r.createElement(r.Fragment,null,t)}function b(){const e=(0,r.useContext)(m);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function y(e){var t;void 0===e&&(e=o.m);const n=(0,a.zh)(e),[i,s]=b(),{preferredVersionName:l}=i[e];return{preferredVersion:null!=(t=n.versions.find((e=>e.name===l)))?t:null,savePreferredVersionName:(0,r.useCallback)((t=>{s.savePreferredVersion(e,t)}),[s,e])}}function w(){const e=(0,a._r)(),[t]=b();function n(n){var r;const a=e[n],{preferredVersionName:o}=t[n];return null!=(r=a.versions.find((e=>e.name===o)))?r:null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>s});var r=n(7294),a=n(902);const o=Symbol("EmptyContext"),i=r.createContext(o);function s(e){let{children:t,name:n,items:a}=e;const o=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return r.createElement(i.Provider,{value:o},t)}function l(){const e=(0,r.useContext)(i);if(e===o)throw new a.i6("DocsSidebarProvider");return e}},3163:(e,t,n)=>{"use strict";n.d(t,{M:()=>d,e:()=>f});var r=n(7294),a=n(3102),o=n(7524),i=n(1980),s=n(6668),l=n(902);const c=r.createContext(void 0);function u(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,s.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[l,c]=(0,r.useState)(!1);(0,i.Rb)((()=>{if(l)return c(!1),!1}));const u=(0,r.useCallback)((()=>{c((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function d(e){let{children:t}=e;const n=u();return r.createElement(c.Provider,{value:n},t)}function f(){const e=r.useContext(c);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>s,Zo:()=>l,n2:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(o.Provider,{value:n},t)}function s(){const e=(0,r.useContext)(o);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const i=(0,r.useContext)(o);if(!i)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,s]=i,l=(0,a.Ql)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},6177:(e,t,n)=>{"use strict";n.d(t,{K:()=>i,M:()=>s});var r=n(7294),a=n(2263),o=n(1980);function i(){return(0,o.Nc)("q")}function s(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,a.Z)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>""+e+n+"?q="+encodeURIComponent(t)),[e,n])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var r=n(7294),a=n(412);const o="desktop",i="mobile",s="ssr";function l(){return a.Z.canUseDOM?window.innerWidth>996?o:i:s}function c(){const[e,t]=(0,r.useState)((()=>l()));return(0,r.useEffect)((()=>{function e(){t(l())}return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(undefined)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>"theme-admonition-"+e},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>"theme-doc-sidebar-item-category-level-"+e,docSidebarItemLinkLevel:e=>"theme-doc-sidebar-item-link-level-"+e},blog:{}}},1442:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>r})},2802:(e,t,n)=>{"use strict";n.d(t,{Wl:()=>f,_F:()=>m,cE:()=>d,hI:()=>w,lO:()=>v,vY:()=>y,oz:()=>b,s1:()=>g});var r=n(7294),a=n(6775),o=n(8790),i=n(143),s=n(373),l=n(1116);function c(e){return Array.from(new Set(e))}var u=n(8596);const d=!!i._r;function f(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=f(t);if(e)return e}}}const p=(e,t)=>void 0!==e&&(0,u.Mg)(e,t);function m(e,t){return"link"===e.type?p(e.href,t):"category"===e.type&&(p(e.href,t)||((e,t)=>e.some((e=>m(e,t))))(e.items,t))}function h(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,u.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,u.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function g(){var e;const t=(0,l.V)(),{pathname:n}=(0,a.TH)();return!1!==(null==(e=(0,i.gA)())?void 0:e.pluginData.breadcrumbs)&&t?h({sidebarItems:t.items,pathname:n}):null}function v(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>c([t,n,a].filter(Boolean))),[t,n,a])}function b(e,t){const n=v(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error("Can't find any sidebar with id \""+e+'" in version'+(n.length>1?"s":"")+" "+n.map((e=>e.name)).join(", ")+'".\nAvailable sidebar ids are:\n- '+t.map((e=>e[0])).join("\n- "));return r[1]}),[e,n])}function y(e,t){const n=v(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error("Couldn't find any doc with id \""+e+'" in version'+(n.length>1?"s":"")+' "'+n.map((e=>e.name)).join(", ")+'".\nAvailable doc ids are:\n- '+c(t.map((e=>e.id))).join("\n- "))}return r}),[e,n])}function w(e){let{route:t,versionMetadata:n}=e;const r=(0,a.TH)(),i=t.routes,s=i.find((e=>(0,a.LX)(r.pathname,e)));if(!s)return null;const l=s.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(i),sidebarName:l,sidebarItems:c}}},2128:(e,t,n)=>{"use strict";n.d(t,{p:()=>a});var r=n(2263);function a(e){const{siteConfig:t}=(0,r.Z)(),{title:n,titleDelimiter:a}=t;return null!=e&&e.trim().length?e.trim()+" "+a+" "+n:n}},1980:(e,t,n)=>{"use strict";n.d(t,{Nc:()=>c,Rb:()=>s});var r=n(7294),a=n(6775),o=n(1688),i=n(902);function s(e){!function(e){const t=(0,a.k6)(),n=(0,i.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function l(e){return function(e){const t=(0,a.k6)();return(0,o.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function c(e){var t;const n=null!=(t=l(e))?t:"",o=function(){const e=(0,a.k6)();return(0,r.useCallback)(((t,n,r)=>{const a=new URLSearchParams(e.location.search);n?a.set(t,n):a.delete(t),(null!=r&&r.push?e.push:e.replace)({search:a.toString()})}),[e])}();return[n,(0,r.useCallback)(((t,n)=>{o(e,t,n)}),[o,e])]}},833:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>u,VC:()=>p});var r=n(7294),a=n(7459),o=n(5742),i=n(226);function s(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2128);function u(e){let{title:t,description:n,keywords:a,image:i,children:s}=e;const u=(0,c.p)(t),{withBaseUrl:d}=(0,l.C)(),f=i?d(i,{absolute:!0}):void 0;return r.createElement(o.Z,null,t&&r.createElement("title",null,u),t&&r.createElement("meta",{property:"og:title",content:u}),n&&r.createElement("meta",{name:"description",content:n}),n&&r.createElement("meta",{property:"og:description",content:n}),a&&r.createElement("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),f&&r.createElement("meta",{property:"og:image",content:f}),f&&r.createElement("meta",{name:"twitter:image",content:f}),s)}const d=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(d),s=(0,a.Z)(i,t);return r.createElement(d.Provider,{value:s},r.createElement(o.Z,null,r.createElement("html",{className:s})),n)}function p(e){let{children:t}=e;const n=s(),o="plugin-"+n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"");const i="plugin-id-"+n.plugin.id;return r.createElement(f,{className:(0,a.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>c,Ql:()=>l,i6:()=>s,zX:()=>o});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function o(e){const t=(0,r.useRef)(e);return a((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return a((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){var n,r,a,o;super(),this.name="ReactContextError",this.message="Hook "+(null!=(n=null==(r=this.stack)||null==(a=r.split("\n")[1])||null==(o=a.match(/at (?:\w+\.)?(?<name>\w+)/))?void 0:o.groups.name)?n:"")+" is called outside the <"+e+">. "+(null!=t?t:"")}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return r.createElement(r.Fragment,null,e.reduceRight(((e,t)=>r.createElement(t,null,e)),n))}}},8022:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{F:()=>r})},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>{var t;return null==(t=!e||e.endsWith("/")?e:e+"/")?void 0:t.toLowerCase()};return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>{var t;return null!=(t=e.routes)?t:[]})))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>l,RF:()=>d});var r=n(7294),a=n(412),o=n(2389),i=n(902);const s=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return r.createElement(s.Provider,{value:n},t)}function c(){const e=(0,r.useContext)(s);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const u=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),a=(0,r.useRef)(u()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&a<e)&&(t=requestAnimationFrame(r),window.scrollTo(0,Math.floor(.85*(a-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>null==e.current?void 0:e.current()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>i,_q:()=>l,os:()=>s});var r=n(143),a=n(2263),o=n(373);const i="default";function s(e,t){return"docs-"+e+"-"+t}function l(){const{i18n:e}=(0,a.Z)(),t=(0,r._r)(),n=(0,r.WS)(),l=(0,o.Oh)();const c=[i,...Object.keys(t).map((function(e){var r;const a=(null==n?void 0:n.activePlugin.pluginId)===e?n.activeVersion:void 0,o=l[e],i=t[e].versions.find((e=>e.isLast));return s(e,(null!=(r=null!=a?a:o)?r:i).name)}))];return{locale:e.currentLocale,tags:c}}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>l});n(7294),n(1688);const r="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,i||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),i=!0),null}var t}let i=!1;const s={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error('Illegal storage API usage for storage key "'+e+'".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.')}return{get:t,set:t,del:t,listen:t}}(e);const n=o(null==t?void 0:t.persistence);return null===n?s:{get:()=>{try{return n.getItem(e)}catch(t){return console.error("Docusaurus storage error, can't get key="+e,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error("Docusaurus storage error, can't set "+e+"="+t,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error("Docusaurus storage error, can't delete key="+e,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error("Docusaurus storage error, can't listen for changes of key="+e,r),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>i});var r=n(2263),a=n(6775),o=n(8780);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.Z)(),{pathname:l}=(0,a.TH)(),c=(0,o.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace("/"+s+"/","/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return""+(r?t:"")+function(e){return e===i?""+u:""+u+e+"/"}(n)+d}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6775),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},6278:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){const{siteConfig:{themeConfig:e}}=(0,r.Z)();return e}},239:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var r=n(7294),a=n(8022),o=n(4996),i=n(6278);function s(){const{withBaseUrl:e}=(0,o.C)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.L)();return(0,r.useCallback)((r=>{const o=new URL(r);if((0,a.F)(t,o.href))return r;const i=""+(o.pathname+o.hash);return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:e+"/"}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},9318:(e,t,n)=>{"use strict";n.d(t,{lX:()=>w,q_:()=>C,ob:()=>p,PP:()=>A,Ep:()=>f});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r<a;n+=1,r+=1)e[n]=e[r];e.pop()}const i=function(e,t){void 0===t&&(t="");var n,r=e&&e.split("/")||[],i=t&&t.split("/")||[],s=e&&a(e),l=t&&a(t),c=s||l;if(e&&a(e)?i=r:r.length&&(i.pop(),i=i.concat(r)),!i.length)return"/";if(i.length){var u=i[i.length-1];n="."===u||".."===u||""===u}else n=!1;for(var d=0,f=i.length;f>=0;f--){var p=i[f];"."===p?o(i,f):".."===p?(o(i,f),d++):d&&(o(i,f),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var s=n(2177);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function p(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.forEach((function(e){return e.apply(void 0,n)}))}}}var h=!("undefined"==typeof window||!window.document||!window.document.createElement);function g(e,t){t(window.confirm(e))}var v="popstate",b="hashchange";function y(){try{return window.history.state||{}}catch(e){return{}}}function w(e){void 0===e&&(e={}),h||(0,s.Z)(!1);var t,n=window.history,a=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,o=!(-1===window.navigator.userAgent.indexOf("Trident")),i=e,c=i.forceRefresh,w=void 0!==c&&c,x=i.getUserConfirmation,k=void 0===x?g:x,E=i.keyLength,S=void 0===E?6:E,_=e.basename?d(l(e.basename)):"";function C(e){var t=e||{},n=t.key,r=t.state,a=window.location,o=a.pathname+a.search+a.hash;return _&&(o=u(o,_)),p(o,r,n)}function T(){return Math.random().toString(36).substr(2,S)}var A=m();function L(e){(0,r.Z)(U,e),U.length=n.length,A.notifyListeners(U.location,U.action)}function R(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||O(C(e.state))}function N(){O(C(y()))}var P=!1;function O(e){if(P)P=!1,L();else{A.confirmTransitionTo(e,"POP",k,(function(t){t?L({action:"POP",location:e}):function(e){var t=U.location,n=D.indexOf(t.key);-1===n&&(n=0);var r=D.indexOf(e.key);-1===r&&(r=0);var a=n-r;a&&(P=!0,F(a))}(e)}))}}var I=C(y()),D=[I.key];function M(e){return _+f(e)}function F(e){n.go(e)}var B=0;function j(e){1===(B+=e)&&1===e?(window.addEventListener(v,R),o&&window.addEventListener(b,N)):0===B&&(window.removeEventListener(v,R),o&&window.removeEventListener(b,N))}var z=!1;var U={length:n.length,action:"POP",location:I,createHref:M,push:function(e,t){var r="PUSH",o=p(e,t,T(),U.location);A.confirmTransitionTo(o,r,k,(function(e){if(e){var t=M(o),i=o.key,s=o.state;if(a)if(n.pushState({key:i,state:s},null,t),w)window.location.href=t;else{var l=D.indexOf(U.location.key),c=D.slice(0,l+1);c.push(o.key),D=c,L({action:r,location:o})}else window.location.href=t}}))},replace:function(e,t){var r="REPLACE",o=p(e,t,T(),U.location);A.confirmTransitionTo(o,r,k,(function(e){if(e){var t=M(o),i=o.key,s=o.state;if(a)if(n.replaceState({key:i,state:s},null,t),w)window.location.replace(t);else{var l=D.indexOf(U.location.key);-1!==l&&(D[l]=o.key),L({action:r,location:o})}else window.location.replace(t)}}))},go:F,goBack:function(){F(-1)},goForward:function(){F(1)},block:function(e){void 0===e&&(e=!1);var t=A.setPrompt(e);return z||(j(1),z=!0),function(){return z&&(z=!1,j(-1)),t()}},listen:function(e){var t=A.appendListener(e);return j(1),function(){j(-1),t()}}};return U}var x="hashchange",k={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+c(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:c,decodePath:l},slash:{encodePath:l,decodePath:l}};function E(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function S(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function _(e){window.location.replace(E(window.location.href)+"#"+e)}function C(e){void 0===e&&(e={}),h||(0,s.Z)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),a=n.getUserConfirmation,o=void 0===a?g:a,i=n.hashType,c=void 0===i?"slash":i,v=e.basename?d(l(e.basename)):"",b=k[c],y=b.encodePath,w=b.decodePath;function C(){var e=w(S());return v&&(e=u(e,v)),p(e)}var T=m();function A(e){(0,r.Z)(z,e),z.length=t.length,T.notifyListeners(z.location,z.action)}var L=!1,R=null;function N(){var e,t,n=S(),r=y(n);if(n!==r)_(r);else{var a=C(),i=z.location;if(!L&&(t=a,(e=i).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(R===f(a))return;R=null,function(e){if(L)L=!1,A();else{var t="POP";T.confirmTransitionTo(e,t,o,(function(n){n?A({action:t,location:e}):function(e){var t=z.location,n=D.lastIndexOf(f(t));-1===n&&(n=0);var r=D.lastIndexOf(f(e));-1===r&&(r=0);var a=n-r;a&&(L=!0,M(a))}(e)}))}}(a)}}var P=S(),O=y(P);P!==O&&_(O);var I=C(),D=[f(I)];function M(e){t.go(e)}var F=0;function B(e){1===(F+=e)&&1===e?window.addEventListener(x,N):0===F&&window.removeEventListener(x,N)}var j=!1;var z={length:t.length,action:"POP",location:I,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=E(window.location.href)),n+"#"+y(v+f(e))},push:function(e,t){var n="PUSH",r=p(e,void 0,void 0,z.location);T.confirmTransitionTo(r,n,o,(function(e){if(e){var t=f(r),a=y(v+t);if(S()!==a){R=t,function(e){window.location.hash=e}(a);var o=D.lastIndexOf(f(z.location)),i=D.slice(0,o+1);i.push(t),D=i,A({action:n,location:r})}else A()}}))},replace:function(e,t){var n="REPLACE",r=p(e,void 0,void 0,z.location);T.confirmTransitionTo(r,n,o,(function(e){if(e){var t=f(r),a=y(v+t);S()!==a&&(R=t,_(a));var o=D.indexOf(f(z.location));-1!==o&&(D[o]=t),A({action:n,location:r})}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=T.setPrompt(e);return j||(B(1),j=!0),function(){return j&&(j=!1,B(-1)),t()}},listen:function(e){var t=T.appendListener(e);return B(1),function(){B(-1),t()}}};return z}function T(e,t,n){return Math.min(Math.max(e,t),n)}function A(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,a=t.initialEntries,o=void 0===a?["/"]:a,i=t.initialIndex,s=void 0===i?0:i,l=t.keyLength,c=void 0===l?6:l,u=m();function d(e){(0,r.Z)(w,e),w.length=w.entries.length,u.notifyListeners(w.location,w.action)}function h(){return Math.random().toString(36).substr(2,c)}var g=T(s,0,o.length-1),v=o.map((function(e){return p(e,void 0,"string"==typeof e?h():e.key||h())})),b=f;function y(e){var t=T(w.index+e,0,w.entries.length-1),r=w.entries[t];u.confirmTransitionTo(r,"POP",n,(function(e){e?d({action:"POP",location:r,index:t}):d()}))}var w={length:v.length,action:"POP",location:v[g],index:g,entries:v,createHref:b,push:function(e,t){var r="PUSH",a=p(e,t,h(),w.location);u.confirmTransitionTo(a,r,n,(function(e){if(e){var t=w.index+1,n=w.entries.slice(0);n.length>t?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=p(e,t,h(),w.location);u.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t<w.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return w}},8679:(e,t,n)=>{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||a}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=p(n);a&&a!==m&&e(t,a,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),h=l(n),g=0;g<i.length;++g){var v=i[g];if(!(o[v]||r&&r[v]||h&&h[v]||s&&s[v])){var b=f(n,v);try{c(t,v,b)}catch(y){}}}}return t}},1143:e=>{"use strict";e.exports=function(e,t,n,r,a,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,a,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function a(e,t,n){return e<t?t:e>n?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(r.barSelector),u=r.speed,d=r.easing;return o.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&p(a),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=f(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(a){return!1}}()?Object.assign:function(e,o){for(var i,s,l=a(e),c=1;c<arguments.length;c++){for(var u in i=Object(arguments[c]))n.call(i,u)&&(l[u]=i[u]);if(t){s=t(i);for(var d=0;d<s.length;d++)r.call(i,s[d])&&(l[s[d]]=i[s[d]])}}return l}},9901:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:"shell",aliasTitles:{shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (Scss)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to <a href="https://webplatform.github.io/docs/">WebPlatform.org documentation</a>. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (<code>.comment</code> can become <code>.namespace--comment</code>) or replace them with your defined ones (like <code>.editor__comment</code>). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the <code>highlightAll</code> and <code>highlightAllUnder</code> methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n]]=!0;return t}function r(e){var n={},r=[];function a(r,o){if(!(r in n)){o.push(r);var i=o.indexOf(r);if(i<o.length-1)throw new Error("Circular dependency: "+o.slice(i).join(" -> "));var s={},l=e[r];if(l){function c(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in s))for(var i in a(t,o),s[t]=!0,n[t])s[i]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[r]=s,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,s){var l=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),c=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(l);i=i.map(c),s=(s||[]).map(c);var u=n(i),d=n(s);i.forEach((function e(n){var r=l[n];t(r&&r.require,(function(t){t in d||(u[t]=!0,e(t))}))}));for(var f,p=r(l),m=u;a(m);){for(var h in f={},m){var g=l[h];t(g&&g.modify,(function(e){e in d&&(f[e]=!0)}))}for(var v in d)if(!(v in u))for(var b in p(v))if(b in u){f[v]=!0;break}for(var y in m=f)u[y]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,s={},l={};function c(e){if(e in s)return s[e];l[e]=!0;var a,u=[];for(var d in t(e))d in n&&u.push(d);if(0===u.length)a=r(e);else{var f=i(u.map((function(e){var t=c(e);return delete l[e],t})));o?a=o(f,(function(){return r(e)})):r(e)}return s[e]=a}for(var u in n)c(u);var d=[];for(var f in l)d.push(s[f]);return i(d)}(p,u,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(7418),o=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}if(!r)throw Error(i(227));var s=new Set,l={};function c(e,t){u(e,t),u(e+"Capture",t)}function u(e,t){for(l[e]=t,e=0;e<t.length;e++)s.add(t[e])}var d=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),f=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,p=Object.prototype.hasOwnProperty,m={},h={};function g(e,t,n,r,a,o,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=i}var v={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){v[e]=new g(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];v[t]=new g(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){v[e]=new g(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){v[e]=new g(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){v[e]=new g(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){v[e]=new g(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){v[e]=new g(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){v[e]=new g(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){v[e]=new g(e,5,!1,e.toLowerCase(),null,!1,!1)}));var b=/[\-:]([a-z])/g;function y(e){return e[1].toUpperCase()}function w(e,t,n,r){var a=v.hasOwnProperty(t)?v[t]:null;(null!==a?0===a.type:!r&&(2<t.length&&("o"===t[0]||"O"===t[0])&&("n"===t[1]||"N"===t[1])))||(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,a,r)&&(n=null),r||null===a?function(e){return!!p.call(h,e)||!p.call(m,e)&&(f.test(e)?h[e]=!0:(m[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):a.mustUseProperty?e[a.propertyName]=null===n?3!==a.type&&"":n:(t=a.attributeName,r=a.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(a=a.type)||4===a&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(b,y);v[t]=new g(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(b,y);v[t]=new g(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(b,y);v[t]=new g(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){v[e]=new g(e,1,!1,e.toLowerCase(),null,!1,!1)})),v.xlinkHref=new g("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){v[e]=new g(e,1,!1,e.toLowerCase(),null,!0,!0)}));var x=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,k=60103,E=60106,S=60107,_=60108,C=60114,T=60109,A=60110,L=60112,R=60113,N=60120,P=60115,O=60116,I=60121,D=60128,M=60129,F=60130,B=60131;if("function"==typeof Symbol&&Symbol.for){var j=Symbol.for;k=j("react.element"),E=j("react.portal"),S=j("react.fragment"),_=j("react.strict_mode"),C=j("react.profiler"),T=j("react.provider"),A=j("react.context"),L=j("react.forward_ref"),R=j("react.suspense"),N=j("react.suspense_list"),P=j("react.memo"),O=j("react.lazy"),I=j("react.block"),j("react.scope"),D=j("react.opaque.id"),M=j("react.debug_trace_mode"),F=j("react.offscreen"),B=j("react.legacy_hidden")}var z,U="function"==typeof Symbol&&Symbol.iterator;function q(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=U&&e[U]||e["@@iterator"])?e:null}function $(e){if(void 0===z)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);z=t&&t[1]||""}return"\n"+z+e}var H=!1;function G(e,t){if(!e||H)return"";H=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(l){var r=l}Reflect.construct(e,[],t)}else{try{t.call()}catch(l){r=l}e.call(t.prototype)}else{try{throw Error()}catch(l){r=l}e()}}catch(l){if(l&&r&&"string"==typeof l.stack){for(var a=l.stack.split("\n"),o=r.stack.split("\n"),i=a.length-1,s=o.length-1;1<=i&&0<=s&&a[i]!==o[s];)s--;for(;1<=i&&0<=s;i--,s--)if(a[i]!==o[s]){if(1!==i||1!==s)do{if(i--,0>--s||a[i]!==o[s])return"\n"+a[i].replace(" at new "," at ")}while(1<=i&&0<=s);break}}}finally{H=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?$(e):""}function Z(e){switch(e.tag){case 5:return $(e.type);case 16:return $("Lazy");case 13:return $("Suspense");case 19:return $("SuspenseList");case 0:case 2:case 15:return e=G(e.type,!1);case 11:return e=G(e.type.render,!1);case 22:return e=G(e.type._render,!1);case 1:return e=G(e.type,!0);default:return""}}function V(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case S:return"Fragment";case E:return"Portal";case C:return"Profiler";case _:return"StrictMode";case R:return"Suspense";case N:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case A:return(e.displayName||"Context")+".Consumer";case T:return(e._context.displayName||"Context")+".Provider";case L:var t=e.render;return t=t.displayName||t.name||"",e.displayName||(""!==t?"ForwardRef("+t+")":"ForwardRef");case P:return V(e.type);case I:return V(e._render);case O:t=e._payload,e=e._init;try{return V(e(t))}catch(n){}}return null}function W(e){switch(typeof e){case"boolean":case"number":case"object":case"string":case"undefined":return e;default:return""}}function K(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function Y(e){e._valueTracker||(e._valueTracker=function(e){var t=K(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var a=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(e){r=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function Q(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=K(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function X(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function J(e,t){var n=t.checked;return a({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function ee(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=W(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function te(e,t){null!=(t=t.checked)&&w(e,"checked",t,!1)}function ne(e,t){te(e,t);var n=W(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ae(e,t.type,n):t.hasOwnProperty("defaultValue")&&ae(e,t.type,W(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function re(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ae(e,t,n){"number"===t&&X(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}function oe(e,t){return e=a({children:void 0},t),(t=function(e){var t="";return r.Children.forEach(e,(function(e){null!=e&&(t+=e)})),t}(t.children))&&(e.children=t),e}function ie(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a<n.length;a++)t["$"+n[a]]=!0;for(n=0;n<e.length;n++)a=t.hasOwnProperty("$"+e[n].value),e[n].selected!==a&&(e[n].selected=a),a&&r&&(e[n].defaultSelected=!0)}else{for(n=""+W(n),t=null,a=0;a<e.length;a++){if(e[a].value===n)return e[a].selected=!0,void(r&&(e[a].defaultSelected=!0));null!==t||e[a].disabled||(t=e[a])}null!==t&&(t.selected=!0)}}function se(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(i(91));return a({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function le(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(i(92));if(Array.isArray(n)){if(!(1>=n.length))throw Error(i(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:W(n)}}function ce(e,t){var n=W(t.value),r=W(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function ue(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}var de="http://www.w3.org/1999/xhtml",fe="http://www.w3.org/2000/svg";function pe(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function me(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?pe(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var he,ge,ve=(ge=function(e,t){if(e.namespaceURI!==fe||"innerHTML"in e)e.innerHTML=t;else{for((he=he||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=he.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction((function(){return ge(e,t)}))}:ge);function be(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var ye={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},we=["Webkit","ms","Moz","O"];function xe(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||ye.hasOwnProperty(e)&&ye[e]?(""+t).trim():t+"px"}function ke(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),a=xe(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}Object.keys(ye).forEach((function(e){we.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ye[t]=ye[e]}))}));var Ee=a({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Se(e,t){if(t){if(Ee[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(i(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(i(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(i(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(i(62))}}function _e(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function Ce(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var Te=null,Ae=null,Le=null;function Re(e){if(e=ra(e)){if("function"!=typeof Te)throw Error(i(280));var t=e.stateNode;t&&(t=oa(t),Te(e.stateNode,e.type,t))}}function Ne(e){Ae?Le?Le.push(e):Le=[e]:Ae=e}function Pe(){if(Ae){var e=Ae,t=Le;if(Le=Ae=null,Re(e),t)for(e=0;e<t.length;e++)Re(t[e])}}function Oe(e,t){return e(t)}function Ie(e,t,n,r,a){return e(t,n,r,a)}function De(){}var Me=Oe,Fe=!1,Be=!1;function je(){null===Ae&&null===Le||(De(),Pe())}function ze(e,t){var n=e.stateNode;if(null===n)return null;var r=oa(n);if(null===r)return null;n=r[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(r=!r.disabled)||(r=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!r;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(i(231,t,typeof n));return n}var Ue=!1;if(d)try{var qe={};Object.defineProperty(qe,"passive",{get:function(){Ue=!0}}),window.addEventListener("test",qe,qe),window.removeEventListener("test",qe,qe)}catch(ge){Ue=!1}function $e(e,t,n,r,a,o,i,s,l){var c=Array.prototype.slice.call(arguments,3);try{t.apply(n,c)}catch(u){this.onError(u)}}var He=!1,Ge=null,Ze=!1,Ve=null,We={onError:function(e){He=!0,Ge=e}};function Ke(e,t,n,r,a,o,i,s,l){He=!1,Ge=null,$e.apply(We,arguments)}function Ye(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{0!=(1026&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function Qe(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function Xe(e){if(Ye(e)!==e)throw Error(i(188))}function Je(e){if(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ye(e)))throw Error(i(188));return t!==e?null:e}for(var n=e,r=t;;){var a=n.return;if(null===a)break;var o=a.alternate;if(null===o){if(null!==(r=a.return)){n=r;continue}break}if(a.child===o.child){for(o=a.child;o;){if(o===n)return Xe(a),e;if(o===r)return Xe(a),t;o=o.sibling}throw Error(i(188))}if(n.return!==r.return)n=a,r=o;else{for(var s=!1,l=a.child;l;){if(l===n){s=!0,n=a,r=o;break}if(l===r){s=!0,r=a,n=o;break}l=l.sibling}if(!s){for(l=o.child;l;){if(l===n){s=!0,n=o,r=a;break}if(l===r){s=!0,r=o,n=a;break}l=l.sibling}if(!s)throw Error(i(189))}}if(n.alternate!==r)throw Error(i(190))}if(3!==n.tag)throw Error(i(188));return n.stateNode.current===n?e:t}(e),!e)return null;for(var t=e;;){if(5===t.tag||6===t.tag)return t;if(t.child)t.child.return=t,t=t.child;else{if(t===e)break;for(;!t.sibling;){if(!t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}}return null}function et(e,t){for(var n=e.alternate;null!==t;){if(t===e||t===n)return!0;t=t.return}return!1}var tt,nt,rt,at,ot=!1,it=[],st=null,lt=null,ct=null,ut=new Map,dt=new Map,ft=[],pt="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function mt(e,t,n,r,a){return{blockedOn:e,domEventName:t,eventSystemFlags:16|n,nativeEvent:a,targetContainers:[r]}}function ht(e,t){switch(e){case"focusin":case"focusout":st=null;break;case"dragenter":case"dragleave":lt=null;break;case"mouseover":case"mouseout":ct=null;break;case"pointerover":case"pointerout":ut.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":dt.delete(t.pointerId)}}function gt(e,t,n,r,a,o){return null===e||e.nativeEvent!==o?(e=mt(t,n,r,a,o),null!==t&&(null!==(t=ra(t))&&nt(t)),e):(e.eventSystemFlags|=r,t=e.targetContainers,null!==a&&-1===t.indexOf(a)&&t.push(a),e)}function vt(e){var t=na(e.target);if(null!==t){var n=Ye(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=Qe(n)))return e.blockedOn=t,void at(e.lanePriority,(function(){o.unstable_runWithPriority(e.priority,(function(){rt(n)}))}))}else if(3===t&&n.stateNode.hydrate)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function bt(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Jt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=ra(n))&&nt(t),e.blockedOn=n,!1;t.shift()}return!0}function yt(e,t,n){bt(e)&&n.delete(t)}function wt(){for(ot=!1;0<it.length;){var e=it[0];if(null!==e.blockedOn){null!==(e=ra(e.blockedOn))&&tt(e);break}for(var t=e.targetContainers;0<t.length;){var n=Jt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n){e.blockedOn=n;break}t.shift()}null===e.blockedOn&&it.shift()}null!==st&&bt(st)&&(st=null),null!==lt&&bt(lt)&&(lt=null),null!==ct&&bt(ct)&&(ct=null),ut.forEach(yt),dt.forEach(yt)}function xt(e,t){e.blockedOn===t&&(e.blockedOn=null,ot||(ot=!0,o.unstable_scheduleCallback(o.unstable_NormalPriority,wt)))}function kt(e){function t(t){return xt(t,e)}if(0<it.length){xt(it[0],e);for(var n=1;n<it.length;n++){var r=it[n];r.blockedOn===e&&(r.blockedOn=null)}}for(null!==st&&xt(st,e),null!==lt&&xt(lt,e),null!==ct&&xt(ct,e),ut.forEach(t),dt.forEach(t),n=0;n<ft.length;n++)(r=ft[n]).blockedOn===e&&(r.blockedOn=null);for(;0<ft.length&&null===(n=ft[0]).blockedOn;)vt(n),null===n.blockedOn&&ft.shift()}function Et(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var St={animationend:Et("Animation","AnimationEnd"),animationiteration:Et("Animation","AnimationIteration"),animationstart:Et("Animation","AnimationStart"),transitionend:Et("Transition","TransitionEnd")},_t={},Ct={};function Tt(e){if(_t[e])return _t[e];if(!St[e])return e;var t,n=St[e];for(t in n)if(n.hasOwnProperty(t)&&t in Ct)return _t[e]=n[t];return e}d&&(Ct=document.createElement("div").style,"AnimationEvent"in window||(delete St.animationend.animation,delete St.animationiteration.animation,delete St.animationstart.animation),"TransitionEvent"in window||delete St.transitionend.transition);var At=Tt("animationend"),Lt=Tt("animationiteration"),Rt=Tt("animationstart"),Nt=Tt("transitionend"),Pt=new Map,Ot=new Map,It=["abort","abort",At,"animationEnd",Lt,"animationIteration",Rt,"animationStart","canplay","canPlay","canplaythrough","canPlayThrough","durationchange","durationChange","emptied","emptied","encrypted","encrypted","ended","ended","error","error","gotpointercapture","gotPointerCapture","load","load","loadeddata","loadedData","loadedmetadata","loadedMetadata","loadstart","loadStart","lostpointercapture","lostPointerCapture","playing","playing","progress","progress","seeking","seeking","stalled","stalled","suspend","suspend","timeupdate","timeUpdate",Nt,"transitionEnd","waiting","waiting"];function Dt(e,t){for(var n=0;n<e.length;n+=2){var r=e[n],a=e[n+1];a="on"+(a[0].toUpperCase()+a.slice(1)),Ot.set(r,t),Pt.set(r,a),c(a,[r])}}(0,o.unstable_now)();var Mt=8;function Ft(e){if(0!=(1&e))return Mt=15,1;if(0!=(2&e))return Mt=14,2;if(0!=(4&e))return Mt=13,4;var t=24&e;return 0!==t?(Mt=12,t):0!=(32&e)?(Mt=11,32):0!==(t=192&e)?(Mt=10,t):0!=(256&e)?(Mt=9,256):0!==(t=3584&e)?(Mt=8,t):0!=(4096&e)?(Mt=7,4096):0!==(t=4186112&e)?(Mt=6,t):0!==(t=62914560&e)?(Mt=5,t):67108864&e?(Mt=4,67108864):0!=(134217728&e)?(Mt=3,134217728):0!==(t=805306368&e)?(Mt=2,t):0!=(1073741824&e)?(Mt=1,1073741824):(Mt=8,e)}function Bt(e,t){var n=e.pendingLanes;if(0===n)return Mt=0;var r=0,a=0,o=e.expiredLanes,i=e.suspendedLanes,s=e.pingedLanes;if(0!==o)r=o,a=Mt=15;else if(0!==(o=134217727&n)){var l=o&~i;0!==l?(r=Ft(l),a=Mt):0!==(s&=o)&&(r=Ft(s),a=Mt)}else 0!==(o=n&~i)?(r=Ft(o),a=Mt):0!==s&&(r=Ft(s),a=Mt);if(0===r)return 0;if(r=n&((0>(r=31-Ht(r))?0:1<<r)<<1)-1,0!==t&&t!==r&&0==(t&i)){if(Ft(t),a<=Mt)return t;Mt=a}if(0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0<t;)a=1<<(n=31-Ht(t)),r|=e[n],t&=~a;return r}function jt(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function zt(e,t){switch(e){case 15:return 1;case 14:return 2;case 12:return 0===(e=Ut(24&~t))?zt(10,t):e;case 10:return 0===(e=Ut(192&~t))?zt(8,t):e;case 8:return 0===(e=Ut(3584&~t))&&(0===(e=Ut(4186112&~t))&&(e=512)),e;case 2:return 0===(t=Ut(805306368&~t))&&(t=268435456),t}throw Error(i(358,e))}function Ut(e){return e&-e}function qt(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function $t(e,t,n){e.pendingLanes|=t;var r=t-1;e.suspendedLanes&=r,e.pingedLanes&=r,(e=e.eventTimes)[t=31-Ht(t)]=n}var Ht=Math.clz32?Math.clz32:function(e){return 0===e?32:31-(Gt(e)/Zt|0)|0},Gt=Math.log,Zt=Math.LN2;var Vt=o.unstable_UserBlockingPriority,Wt=o.unstable_runWithPriority,Kt=!0;function Yt(e,t,n,r){Fe||De();var a=Xt,o=Fe;Fe=!0;try{Ie(a,e,t,n,r)}finally{(Fe=o)||je()}}function Qt(e,t,n,r){Wt(Vt,Xt.bind(null,e,t,n,r))}function Xt(e,t,n,r){var a;if(Kt)if((a=0==(4&t))&&0<it.length&&-1<pt.indexOf(e))e=mt(null,e,t,n,r),it.push(e);else{var o=Jt(e,t,n,r);if(null===o)a&&ht(e,r);else{if(a){if(-1<pt.indexOf(e))return e=mt(o,e,t,n,r),void it.push(e);if(function(e,t,n,r,a){switch(t){case"focusin":return st=gt(st,e,t,n,r,a),!0;case"dragenter":return lt=gt(lt,e,t,n,r,a),!0;case"mouseover":return ct=gt(ct,e,t,n,r,a),!0;case"pointerover":var o=a.pointerId;return ut.set(o,gt(ut.get(o)||null,e,t,n,r,a)),!0;case"gotpointercapture":return o=a.pointerId,dt.set(o,gt(dt.get(o)||null,e,t,n,r,a)),!0}return!1}(o,e,t,n,r))return;ht(e,r)}Dr(e,t,r,null,n)}}}function Jt(e,t,n,r){var a=Ce(r);if(null!==(a=na(a))){var o=Ye(a);if(null===o)a=null;else{var i=o.tag;if(13===i){if(null!==(a=Qe(o)))return a;a=null}else if(3===i){if(o.stateNode.hydrate)return 3===o.tag?o.stateNode.containerInfo:null;a=null}else o!==a&&(a=null)}}return Dr(e,t,r,a,n),null}var en=null,tn=null,nn=null;function rn(){if(nn)return nn;var e,t,n=tn,r=n.length,a="value"in en?en.value:en.textContent,o=a.length;for(e=0;e<r&&n[e]===a[e];e++);var i=r-e;for(t=1;t<=i&&n[r-t]===a[o-t];t++);return nn=a.slice(e,1<t?1-t:void 0)}function an(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function on(){return!0}function sn(){return!1}function ln(e){function t(t,n,r,a,o){for(var i in this._reactName=t,this._targetInst=r,this.type=n,this.nativeEvent=a,this.target=o,this.currentTarget=null,e)e.hasOwnProperty(i)&&(t=e[i],this[i]=t?t(a):a[i]);return this.isDefaultPrevented=(null!=a.defaultPrevented?a.defaultPrevented:!1===a.returnValue)?on:sn,this.isPropagationStopped=sn,this}return a(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=on)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=on)},persist:function(){},isPersistent:on}),t}var cn,un,dn,fn={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},pn=ln(fn),mn=a({},fn,{view:0,detail:0}),hn=ln(mn),gn=a({},mn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:An,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==dn&&(dn&&"mousemove"===e.type?(cn=e.screenX-dn.screenX,un=e.screenY-dn.screenY):un=cn=0,dn=e),cn)},movementY:function(e){return"movementY"in e?e.movementY:un}}),vn=ln(gn),bn=ln(a({},gn,{dataTransfer:0})),yn=ln(a({},mn,{relatedTarget:0})),wn=ln(a({},fn,{animationName:0,elapsedTime:0,pseudoElement:0})),xn=a({},fn,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),kn=ln(xn),En=ln(a({},fn,{data:0})),Sn={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},_n={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},Cn={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function Tn(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=Cn[e])&&!!t[e]}function An(){return Tn}var Ln=a({},mn,{key:function(e){if(e.key){var t=Sn[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=an(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?_n[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:An,charCode:function(e){return"keypress"===e.type?an(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?an(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),Rn=ln(Ln),Nn=ln(a({},gn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),Pn=ln(a({},mn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:An})),On=ln(a({},fn,{propertyName:0,elapsedTime:0,pseudoElement:0})),In=a({},gn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),Dn=ln(In),Mn=[9,13,27,32],Fn=d&&"CompositionEvent"in window,Bn=null;d&&"documentMode"in document&&(Bn=document.documentMode);var jn=d&&"TextEvent"in window&&!Bn,zn=d&&(!Fn||Bn&&8<Bn&&11>=Bn),Un=String.fromCharCode(32),qn=!1;function $n(e,t){switch(e){case"keyup":return-1!==Mn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Hn(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Gn=!1;var Zn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Vn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Zn[e.type]:"textarea"===t}function Wn(e,t,n,r){Ne(r),0<(t=Fr(t,"onChange")).length&&(n=new pn("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Kn=null,Yn=null;function Qn(e){Lr(e,0)}function Xn(e){if(Q(aa(e)))return e}function Jn(e,t){if("change"===e)return t}var er=!1;if(d){var tr;if(d){var nr="oninput"in document;if(!nr){var rr=document.createElement("div");rr.setAttribute("oninput","return;"),nr="function"==typeof rr.oninput}tr=nr}else tr=!1;er=tr&&(!document.documentMode||9<document.documentMode)}function ar(){Kn&&(Kn.detachEvent("onpropertychange",or),Yn=Kn=null)}function or(e){if("value"===e.propertyName&&Xn(Yn)){var t=[];if(Wn(t,Yn,e,Ce(e)),e=Qn,Fe)e(t);else{Fe=!0;try{Oe(e,t)}finally{Fe=!1,je()}}}}function ir(e,t,n){"focusin"===e?(ar(),Yn=n,(Kn=t).attachEvent("onpropertychange",or)):"focusout"===e&&ar()}function sr(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Xn(Yn)}function lr(e,t){if("click"===e)return Xn(t)}function cr(e,t){if("input"===e||"change"===e)return Xn(t)}var ur="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},dr=Object.prototype.hasOwnProperty;function fr(e,t){if(ur(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++)if(!dr.call(t,n[r])||!ur(e[n[r]],t[n[r]]))return!1;return!0}function pr(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function mr(e,t){var n,r=pr(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=pr(r)}}function hr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?hr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function gr(){for(var e=window,t=X();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=X((e=t.contentWindow).document)}return t}function vr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var br=d&&"documentMode"in document&&11>=document.documentMode,yr=null,wr=null,xr=null,kr=!1;function Er(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;kr||null==yr||yr!==X(r)||("selectionStart"in(r=yr)&&vr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},xr&&fr(xr,r)||(xr=r,0<(r=Fr(wr,"onSelect")).length&&(t=new pn("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=yr)))}Dt("cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focusin focus focusout blur input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange".split(" "),0),Dt("drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel".split(" "),1),Dt(It,2);for(var Sr="change selectionchange textInput compositionstart compositionend compositionupdate".split(" "),_r=0;_r<Sr.length;_r++)Ot.set(Sr[_r],0);u("onMouseEnter",["mouseout","mouseover"]),u("onMouseLeave",["mouseout","mouseover"]),u("onPointerEnter",["pointerout","pointerover"]),u("onPointerLeave",["pointerout","pointerover"]),c("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),c("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),c("onBeforeInput",["compositionend","keypress","textInput","paste"]),c("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),c("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Cr="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Tr=new Set("cancel close invalid load scroll toggle".split(" ").concat(Cr));function Ar(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,r,a,o,s,l,c){if(Ke.apply(this,arguments),He){if(!He)throw Error(i(198));var u=Ge;He=!1,Ge=null,Ze||(Ze=!0,Ve=u)}}(r,t,void 0,e),e.currentTarget=null}function Lr(e,t){t=0!=(4&t);for(var n=0;n<e.length;n++){var r=e[n],a=r.event;r=r.listeners;e:{var o=void 0;if(t)for(var i=r.length-1;0<=i;i--){var s=r[i],l=s.instance,c=s.currentTarget;if(s=s.listener,l!==o&&a.isPropagationStopped())break e;Ar(a,s,c),o=l}else for(i=0;i<r.length;i++){if(l=(s=r[i]).instance,c=s.currentTarget,s=s.listener,l!==o&&a.isPropagationStopped())break e;Ar(a,s,c),o=l}}}if(Ze)throw e=Ve,Ze=!1,Ve=null,e}function Rr(e,t){var n=ia(t),r=e+"__bubble";n.has(r)||(Ir(t,e,2,!1),n.add(r))}var Nr="_reactListening"+Math.random().toString(36).slice(2);function Pr(e){e[Nr]||(e[Nr]=!0,s.forEach((function(t){Tr.has(t)||Or(t,!1,e,null),Or(t,!0,e,null)})))}function Or(e,t,n,r){var a=4<arguments.length&&void 0!==arguments[4]?arguments[4]:0,o=n;if("selectionchange"===e&&9!==n.nodeType&&(o=n.ownerDocument),null!==r&&!t&&Tr.has(e)){if("scroll"!==e)return;a|=2,o=r}var i=ia(o),s=e+"__"+(t?"capture":"bubble");i.has(s)||(t&&(a|=4),Ir(o,e,a,t),i.add(s))}function Ir(e,t,n,r){var a=Ot.get(t);switch(void 0===a?2:a){case 0:a=Yt;break;case 1:a=Qt;break;default:a=Xt}n=a.bind(null,t,n,e),a=void 0,!Ue||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(a=!0),r?void 0!==a?e.addEventListener(t,n,{capture:!0,passive:a}):e.addEventListener(t,n,!0):void 0!==a?e.addEventListener(t,n,{passive:a}):e.addEventListener(t,n,!1)}function Dr(e,t,n,r,a){var o=r;if(0==(1&t)&&0==(2&t)&&null!==r)e:for(;;){if(null===r)return;var i=r.tag;if(3===i||4===i){var s=r.stateNode.containerInfo;if(s===a||8===s.nodeType&&s.parentNode===a)break;if(4===i)for(i=r.return;null!==i;){var l=i.tag;if((3===l||4===l)&&((l=i.stateNode.containerInfo)===a||8===l.nodeType&&l.parentNode===a))return;i=i.return}for(;null!==s;){if(null===(i=na(s)))return;if(5===(l=i.tag)||6===l){r=o=i;continue e}s=s.parentNode}}r=r.return}!function(e,t,n){if(Be)return e(t,n);Be=!0;try{Me(e,t,n)}finally{Be=!1,je()}}((function(){var r=o,a=Ce(n),i=[];e:{var s=Pt.get(e);if(void 0!==s){var l=pn,c=e;switch(e){case"keypress":if(0===an(n))break e;case"keydown":case"keyup":l=Rn;break;case"focusin":c="focus",l=yn;break;case"focusout":c="blur",l=yn;break;case"beforeblur":case"afterblur":l=yn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":l=vn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":l=bn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":l=Pn;break;case At:case Lt:case Rt:l=wn;break;case Nt:l=On;break;case"scroll":l=hn;break;case"wheel":l=Dn;break;case"copy":case"cut":case"paste":l=kn;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":l=Nn}var u=0!=(4&t),d=!u&&"scroll"===e,f=u?null!==s?s+"Capture":null:s;u=[];for(var p,m=r;null!==m;){var h=(p=m).stateNode;if(5===p.tag&&null!==h&&(p=h,null!==f&&(null!=(h=ze(m,f))&&u.push(Mr(m,h,p)))),d)break;m=m.return}0<u.length&&(s=new l(s,c,null,n,a),i.push({event:s,listeners:u}))}}if(0==(7&t)){if(l="mouseout"===e||"pointerout"===e,(!(s="mouseover"===e||"pointerover"===e)||0!=(16&t)||!(c=n.relatedTarget||n.fromElement)||!na(c)&&!c[ea])&&(l||s)&&(s=a.window===a?a:(s=a.ownerDocument)?s.defaultView||s.parentWindow:window,l?(l=r,null!==(c=(c=n.relatedTarget||n.toElement)?na(c):null)&&(c!==(d=Ye(c))||5!==c.tag&&6!==c.tag)&&(c=null)):(l=null,c=r),l!==c)){if(u=vn,h="onMouseLeave",f="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(u=Nn,h="onPointerLeave",f="onPointerEnter",m="pointer"),d=null==l?s:aa(l),p=null==c?s:aa(c),(s=new u(h,m+"leave",l,n,a)).target=d,s.relatedTarget=p,h=null,na(a)===r&&((u=new u(f,m+"enter",c,n,a)).target=p,u.relatedTarget=d,h=u),d=h,l&&c)e:{for(f=c,m=0,p=u=l;p;p=Br(p))m++;for(p=0,h=f;h;h=Br(h))p++;for(;0<m-p;)u=Br(u),m--;for(;0<p-m;)f=Br(f),p--;for(;m--;){if(u===f||null!==f&&u===f.alternate)break e;u=Br(u),f=Br(f)}u=null}else u=null;null!==l&&jr(i,s,l,u,!1),null!==c&&null!==d&&jr(i,d,c,u,!0)}if("select"===(l=(s=r?aa(r):window).nodeName&&s.nodeName.toLowerCase())||"input"===l&&"file"===s.type)var g=Jn;else if(Vn(s))if(er)g=cr;else{g=sr;var v=ir}else(l=s.nodeName)&&"input"===l.toLowerCase()&&("checkbox"===s.type||"radio"===s.type)&&(g=lr);switch(g&&(g=g(e,r))?Wn(i,g,n,a):(v&&v(e,s,r),"focusout"===e&&(v=s._wrapperState)&&v.controlled&&"number"===s.type&&ae(s,"number",s.value)),v=r?aa(r):window,e){case"focusin":(Vn(v)||"true"===v.contentEditable)&&(yr=v,wr=r,xr=null);break;case"focusout":xr=wr=yr=null;break;case"mousedown":kr=!0;break;case"contextmenu":case"mouseup":case"dragend":kr=!1,Er(i,n,a);break;case"selectionchange":if(br)break;case"keydown":case"keyup":Er(i,n,a)}var b;if(Fn)e:{switch(e){case"compositionstart":var y="onCompositionStart";break e;case"compositionend":y="onCompositionEnd";break e;case"compositionupdate":y="onCompositionUpdate";break e}y=void 0}else Gn?$n(e,n)&&(y="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(y="onCompositionStart");y&&(zn&&"ko"!==n.locale&&(Gn||"onCompositionStart"!==y?"onCompositionEnd"===y&&Gn&&(b=rn()):(tn="value"in(en=a)?en.value:en.textContent,Gn=!0)),0<(v=Fr(r,y)).length&&(y=new En(y,e,null,n,a),i.push({event:y,listeners:v}),b?y.data=b:null!==(b=Hn(n))&&(y.data=b))),(b=jn?function(e,t){switch(e){case"compositionend":return Hn(t);case"keypress":return 32!==t.which?null:(qn=!0,Un);case"textInput":return(e=t.data)===Un&&qn?null:e;default:return null}}(e,n):function(e,t){if(Gn)return"compositionend"===e||!Fn&&$n(e,t)?(e=rn(),nn=tn=en=null,Gn=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return zn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(r=Fr(r,"onBeforeInput")).length&&(a=new En("onBeforeInput","beforeinput",null,n,a),i.push({event:a,listeners:r}),a.data=b))}Lr(i,t)}))}function Mr(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Fr(e,t){for(var n=t+"Capture",r=[];null!==e;){var a=e,o=a.stateNode;5===a.tag&&null!==o&&(a=o,null!=(o=ze(e,n))&&r.unshift(Mr(e,o,a)),null!=(o=ze(e,t))&&r.push(Mr(e,o,a))),e=e.return}return r}function Br(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function jr(e,t,n,r,a){for(var o=t._reactName,i=[];null!==n&&n!==r;){var s=n,l=s.alternate,c=s.stateNode;if(null!==l&&l===r)break;5===s.tag&&null!==c&&(s=c,a?null!=(l=ze(n,o))&&i.unshift(Mr(n,l,s)):a||null!=(l=ze(n,o))&&i.push(Mr(n,l,s))),n=n.return}0!==i.length&&e.push({event:t,listeners:i})}function zr(){}var Ur=null,qr=null;function $r(e,t){switch(e){case"button":case"input":case"select":case"textarea":return!!t.autoFocus}return!1}function Hr(e,t){return"textarea"===e||"option"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var Gr="function"==typeof setTimeout?setTimeout:void 0,Zr="function"==typeof clearTimeout?clearTimeout:void 0;function Vr(e){1===e.nodeType?e.textContent="":9===e.nodeType&&(null!=(e=e.body)&&(e.textContent=""))}function Wr(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break}return e}function Kr(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var Yr=0;var Qr=Math.random().toString(36).slice(2),Xr="__reactFiber$"+Qr,Jr="__reactProps$"+Qr,ea="__reactContainer$"+Qr,ta="__reactEvents$"+Qr;function na(e){var t=e[Xr];if(t)return t;for(var n=e.parentNode;n;){if(t=n[ea]||n[Xr]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=Kr(e);null!==e;){if(n=e[Xr])return n;e=Kr(e)}return t}n=(e=n).parentNode}return null}function ra(e){return!(e=e[Xr]||e[ea])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function aa(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(i(33))}function oa(e){return e[Jr]||null}function ia(e){var t=e[ta];return void 0===t&&(t=e[ta]=new Set),t}var sa=[],la=-1;function ca(e){return{current:e}}function ua(e){0>la||(e.current=sa[la],sa[la]=null,la--)}function da(e,t){la++,sa[la]=e.current,e.current=t}var fa={},pa=ca(fa),ma=ca(!1),ha=fa;function ga(e,t){var n=e.type.contextTypes;if(!n)return fa;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a,o={};for(a in n)o[a]=t[a];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function va(e){return null!=(e=e.childContextTypes)}function ba(){ua(ma),ua(pa)}function ya(e,t,n){if(pa.current!==fa)throw Error(i(168));da(pa,t),da(ma,n)}function wa(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var o in r=r.getChildContext())if(!(o in e))throw Error(i(108,V(t)||"Unknown",o));return a({},n,r)}function xa(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||fa,ha=pa.current,da(pa,e),da(ma,ma.current),!0}function ka(e,t,n){var r=e.stateNode;if(!r)throw Error(i(169));n?(e=wa(e,t,ha),r.__reactInternalMemoizedMergedChildContext=e,ua(ma),ua(pa),da(pa,e)):ua(ma),da(ma,n)}var Ea=null,Sa=null,_a=o.unstable_runWithPriority,Ca=o.unstable_scheduleCallback,Ta=o.unstable_cancelCallback,Aa=o.unstable_shouldYield,La=o.unstable_requestPaint,Ra=o.unstable_now,Na=o.unstable_getCurrentPriorityLevel,Pa=o.unstable_ImmediatePriority,Oa=o.unstable_UserBlockingPriority,Ia=o.unstable_NormalPriority,Da=o.unstable_LowPriority,Ma=o.unstable_IdlePriority,Fa={},Ba=void 0!==La?La:function(){},ja=null,za=null,Ua=!1,qa=Ra(),$a=1e4>qa?Ra:function(){return Ra()-qa};function Ha(){switch(Na()){case Pa:return 99;case Oa:return 98;case Ia:return 97;case Da:return 96;case Ma:return 95;default:throw Error(i(332))}}function Ga(e){switch(e){case 99:return Pa;case 98:return Oa;case 97:return Ia;case 96:return Da;case 95:return Ma;default:throw Error(i(332))}}function Za(e,t){return e=Ga(e),_a(e,t)}function Va(e,t,n){return e=Ga(e),Ca(e,t,n)}function Wa(){if(null!==za){var e=za;za=null,Ta(e)}Ka()}function Ka(){if(!Ua&&null!==ja){Ua=!0;var e=0;try{var t=ja;Za(99,(function(){for(;e<t.length;e++){var n=t[e];do{n=n(!0)}while(null!==n)}})),ja=null}catch(n){throw null!==ja&&(ja=ja.slice(e+1)),Ca(Pa,Wa),n}finally{Ua=!1}}}var Ya=x.ReactCurrentBatchConfig;function Qa(e,t){if(e&&e.defaultProps){for(var n in t=a({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}var Xa=ca(null),Ja=null,eo=null,to=null;function no(){to=eo=Ja=null}function ro(e){var t=Xa.current;ua(Xa),e.type._context._currentValue=t}function ao(e,t){for(;null!==e;){var n=e.alternate;if((e.childLanes&t)===t){if(null===n||(n.childLanes&t)===t)break;n.childLanes|=t}else e.childLanes|=t,null!==n&&(n.childLanes|=t);e=e.return}}function oo(e,t){Ja=e,to=eo=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(0!=(e.lanes&t)&&(Fi=!0),e.firstContext=null)}function io(e,t){if(to!==e&&!1!==t&&0!==t)if("number"==typeof t&&1073741823!==t||(to=e,t=1073741823),t={context:e,observedBits:t,next:null},null===eo){if(null===Ja)throw Error(i(308));eo=t,Ja.dependencies={lanes:0,firstContext:t,responders:null}}else eo=eo.next=t;return e._currentValue}var so=!1;function lo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null},effects:null}}function co(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function uo(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function fo(e,t){if(null!==(e=e.updateQueue)){var n=(e=e.shared).pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}}function po(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var a=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===o?a=o=i:o=o.next=i,n=n.next}while(null!==n);null===o?a=o=t:o=o.next=t}else a=o=t;return n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:o,shared:r.shared,effects:r.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function mo(e,t,n,r){var o=e.updateQueue;so=!1;var i=o.firstBaseUpdate,s=o.lastBaseUpdate,l=o.shared.pending;if(null!==l){o.shared.pending=null;var c=l,u=c.next;c.next=null,null===s?i=u:s.next=u,s=c;var d=e.alternate;if(null!==d){var f=(d=d.updateQueue).lastBaseUpdate;f!==s&&(null===f?d.firstBaseUpdate=u:f.next=u,d.lastBaseUpdate=c)}}if(null!==i){for(f=o.baseState,s=0,d=u=c=null;;){l=i.lane;var p=i.eventTime;if((r&l)===l){null!==d&&(d=d.next={eventTime:p,lane:0,tag:i.tag,payload:i.payload,callback:i.callback,next:null});e:{var m=e,h=i;switch(l=t,p=n,h.tag){case 1:if("function"==typeof(m=h.payload)){f=m.call(p,f,l);break e}f=m;break e;case 3:m.flags=-4097&m.flags|64;case 0:if(null==(l="function"==typeof(m=h.payload)?m.call(p,f,l):m))break e;f=a({},f,l);break e;case 2:so=!0}}null!==i.callback&&(e.flags|=32,null===(l=o.effects)?o.effects=[i]:l.push(i))}else p={eventTime:p,lane:l,tag:i.tag,payload:i.payload,callback:i.callback,next:null},null===d?(u=d=p,c=f):d=d.next=p,s|=l;if(null===(i=i.next)){if(null===(l=o.shared.pending))break;i=l.next,l.next=null,o.lastBaseUpdate=l,o.shared.pending=null}}null===d&&(c=f),o.baseState=c,o.firstBaseUpdate=u,o.lastBaseUpdate=d,Us|=s,e.lanes=s,e.memoizedState=f}}function ho(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var r=e[t],a=r.callback;if(null!==a){if(r.callback=null,r=n,"function"!=typeof a)throw Error(i(191,a));a.call(r)}}}var go=(new r.Component).refs;function vo(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:a({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var bo={isMounted:function(e){return!!(e=e._reactInternals)&&Ye(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var r=fl(),a=pl(e),o=uo(r,a);o.payload=t,null!=n&&(o.callback=n),fo(e,o),ml(e,a,r)},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=fl(),a=pl(e),o=uo(r,a);o.tag=1,o.payload=t,null!=n&&(o.callback=n),fo(e,o),ml(e,a,r)},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=fl(),r=pl(e),a=uo(n,r);a.tag=2,null!=t&&(a.callback=t),fo(e,a),ml(e,r,n)}};function yo(e,t,n,r,a,o,i){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,o,i):!t.prototype||!t.prototype.isPureReactComponent||(!fr(n,r)||!fr(a,o))}function wo(e,t,n){var r=!1,a=fa,o=t.contextType;return"object"==typeof o&&null!==o?o=io(o):(a=va(t)?ha:pa.current,o=(r=null!=(r=t.contextTypes))?ga(e,a):fa),t=new t(n,o),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=bo,e.stateNode=t,t._reactInternals=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=a,e.__reactInternalMemoizedMaskedChildContext=o),t}function xo(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&bo.enqueueReplaceState(t,t.state,null)}function ko(e,t,n,r){var a=e.stateNode;a.props=n,a.state=e.memoizedState,a.refs=go,lo(e);var o=t.contextType;"object"==typeof o&&null!==o?a.context=io(o):(o=va(t)?ha:pa.current,a.context=ga(e,o)),mo(e,n,a,r),a.state=e.memoizedState,"function"==typeof(o=t.getDerivedStateFromProps)&&(vo(e,t,o,n),a.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof a.getSnapshotBeforeUpdate||"function"!=typeof a.UNSAFE_componentWillMount&&"function"!=typeof a.componentWillMount||(t=a.state,"function"==typeof a.componentWillMount&&a.componentWillMount(),"function"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount(),t!==a.state&&bo.enqueueReplaceState(a,a.state,null),mo(e,n,a,r),a.state=e.memoizedState),"function"==typeof a.componentDidMount&&(e.flags|=4)}var Eo=Array.isArray;function So(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(i(309));var r=n.stateNode}if(!r)throw Error(i(147,e));var a=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===a?t.ref:(t=function(e){var t=r.refs;t===go&&(t=r.refs={}),null===e?delete t[a]:t[a]=e},t._stringRef=a,t)}if("string"!=typeof e)throw Error(i(284));if(!n._owner)throw Error(i(290,e))}return e}function _o(e,t){if("textarea"!==e.type)throw Error(i(31,"[object Object]"===Object.prototype.toString.call(t)?"object with keys {"+Object.keys(t).join(", ")+"}":t))}function Co(e){function t(t,n){if(e){var r=t.lastEffect;null!==r?(r.nextEffect=n,t.lastEffect=n):t.firstEffect=t.lastEffect=n,n.nextEffect=null,n.flags=8}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function a(e,t){return(e=Zl(e,t)).index=0,e.sibling=null,e}function o(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)<n?(t.flags=2,n):r:(t.flags=2,n):n}function s(t){return e&&null===t.alternate&&(t.flags=2),t}function l(e,t,n,r){return null===t||6!==t.tag?((t=Yl(n,e.mode,r)).return=e,t):((t=a(t,n)).return=e,t)}function c(e,t,n,r){return null!==t&&t.elementType===n.type?((r=a(t,n.props)).ref=So(e,t,n),r.return=e,r):((r=Vl(n.type,n.key,n.props,null,e.mode,r)).ref=So(e,t,n),r.return=e,r)}function u(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=Ql(n,e.mode,r)).return=e,t):((t=a(t,n.children||[])).return=e,t)}function d(e,t,n,r,o){return null===t||7!==t.tag?((t=Wl(n,e.mode,r,o)).return=e,t):((t=a(t,n)).return=e,t)}function f(e,t,n){if("string"==typeof t||"number"==typeof t)return(t=Yl(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case k:return(n=Vl(t.type,t.key,t.props,null,e.mode,n)).ref=So(e,null,t),n.return=e,n;case E:return(t=Ql(t,e.mode,n)).return=e,t}if(Eo(t)||q(t))return(t=Wl(t,e.mode,n,null)).return=e,t;_o(e,t)}return null}function p(e,t,n,r){var a=null!==t?t.key:null;if("string"==typeof n||"number"==typeof n)return null!==a?null:l(e,t,""+n,r);if("object"==typeof n&&null!==n){switch(n.$$typeof){case k:return n.key===a?n.type===S?d(e,t,n.props.children,r,a):c(e,t,n,r):null;case E:return n.key===a?u(e,t,n,r):null}if(Eo(n)||q(n))return null!==a?null:d(e,t,n,r,null);_o(e,n)}return null}function m(e,t,n,r,a){if("string"==typeof r||"number"==typeof r)return l(t,e=e.get(n)||null,""+r,a);if("object"==typeof r&&null!==r){switch(r.$$typeof){case k:return e=e.get(null===r.key?n:r.key)||null,r.type===S?d(t,e,r.props.children,a,r.key):c(t,e,r,a);case E:return u(t,e=e.get(null===r.key?n:r.key)||null,r,a)}if(Eo(r)||q(r))return d(t,e=e.get(n)||null,r,a,null);_o(t,r)}return null}function h(a,i,s,l){for(var c=null,u=null,d=i,h=i=0,g=null;null!==d&&h<s.length;h++){d.index>h?(g=d,d=null):g=d.sibling;var v=p(a,d,s[h],l);if(null===v){null===d&&(d=g);break}e&&d&&null===v.alternate&&t(a,d),i=o(v,i,h),null===u?c=v:u.sibling=v,u=v,d=g}if(h===s.length)return n(a,d),c;if(null===d){for(;h<s.length;h++)null!==(d=f(a,s[h],l))&&(i=o(d,i,h),null===u?c=d:u.sibling=d,u=d);return c}for(d=r(a,d);h<s.length;h++)null!==(g=m(d,a,h,s[h],l))&&(e&&null!==g.alternate&&d.delete(null===g.key?h:g.key),i=o(g,i,h),null===u?c=g:u.sibling=g,u=g);return e&&d.forEach((function(e){return t(a,e)})),c}function g(a,s,l,c){var u=q(l);if("function"!=typeof u)throw Error(i(150));if(null==(l=u.call(l)))throw Error(i(151));for(var d=u=null,h=s,g=s=0,v=null,b=l.next();null!==h&&!b.done;g++,b=l.next()){h.index>g?(v=h,h=null):v=h.sibling;var y=p(a,h,b.value,c);if(null===y){null===h&&(h=v);break}e&&h&&null===y.alternate&&t(a,h),s=o(y,s,g),null===d?u=y:d.sibling=y,d=y,h=v}if(b.done)return n(a,h),u;if(null===h){for(;!b.done;g++,b=l.next())null!==(b=f(a,b.value,c))&&(s=o(b,s,g),null===d?u=b:d.sibling=b,d=b);return u}for(h=r(a,h);!b.done;g++,b=l.next())null!==(b=m(h,a,g,b.value,c))&&(e&&null!==b.alternate&&h.delete(null===b.key?g:b.key),s=o(b,s,g),null===d?u=b:d.sibling=b,d=b);return e&&h.forEach((function(e){return t(a,e)})),u}return function(e,r,o,l){var c="object"==typeof o&&null!==o&&o.type===S&&null===o.key;c&&(o=o.props.children);var u="object"==typeof o&&null!==o;if(u)switch(o.$$typeof){case k:e:{for(u=o.key,c=r;null!==c;){if(c.key===u){if(7===c.tag){if(o.type===S){n(e,c.sibling),(r=a(c,o.props.children)).return=e,e=r;break e}}else if(c.elementType===o.type){n(e,c.sibling),(r=a(c,o.props)).ref=So(e,c,o),r.return=e,e=r;break e}n(e,c);break}t(e,c),c=c.sibling}o.type===S?((r=Wl(o.props.children,e.mode,l,o.key)).return=e,e=r):((l=Vl(o.type,o.key,o.props,null,e.mode,l)).ref=So(e,r,o),l.return=e,e=l)}return s(e);case E:e:{for(c=o.key;null!==r;){if(r.key===c){if(4===r.tag&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),(r=a(r,o.children||[])).return=e,e=r;break e}n(e,r);break}t(e,r),r=r.sibling}(r=Ql(o,e.mode,l)).return=e,e=r}return s(e)}if("string"==typeof o||"number"==typeof o)return o=""+o,null!==r&&6===r.tag?(n(e,r.sibling),(r=a(r,o)).return=e,e=r):(n(e,r),(r=Yl(o,e.mode,l)).return=e,e=r),s(e);if(Eo(o))return h(e,r,o,l);if(q(o))return g(e,r,o,l);if(u&&_o(e,o),void 0===o&&!c)switch(e.tag){case 1:case 22:case 0:case 11:case 15:throw Error(i(152,V(e.type)||"Component"))}return n(e,r)}}var To=Co(!0),Ao=Co(!1),Lo={},Ro=ca(Lo),No=ca(Lo),Po=ca(Lo);function Oo(e){if(e===Lo)throw Error(i(174));return e}function Io(e,t){switch(da(Po,t),da(No,e),da(Ro,Lo),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:me(null,"");break;default:t=me(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}ua(Ro),da(Ro,t)}function Do(){ua(Ro),ua(No),ua(Po)}function Mo(e){Oo(Po.current);var t=Oo(Ro.current),n=me(t,e.type);t!==n&&(da(No,e),da(Ro,n))}function Fo(e){No.current===e&&(ua(Ro),ua(No))}var Bo=ca(0);function jo(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var zo=null,Uo=null,qo=!1;function $o(e,t){var n=Hl(5,null,null,0);n.elementType="DELETED",n.type="DELETED",n.stateNode=t,n.return=e,n.flags=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function Ho(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);default:return!1}}function Go(e){if(qo){var t=Uo;if(t){var n=t;if(!Ho(e,t)){if(!(t=Wr(n.nextSibling))||!Ho(e,t))return e.flags=-1025&e.flags|2,qo=!1,void(zo=e);$o(zo,n)}zo=e,Uo=Wr(t.firstChild)}else e.flags=-1025&e.flags|2,qo=!1,zo=e}}function Zo(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;zo=e}function Vo(e){if(e!==zo)return!1;if(!qo)return Zo(e),qo=!0,!1;var t=e.type;if(5!==e.tag||"head"!==t&&"body"!==t&&!Hr(t,e.memoizedProps))for(t=Uo;t;)$o(e,t),t=Wr(t.nextSibling);if(Zo(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(i(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){Uo=Wr(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}Uo=null}}else Uo=zo?Wr(e.stateNode.nextSibling):null;return!0}function Wo(){Uo=zo=null,qo=!1}var Ko=[];function Yo(){for(var e=0;e<Ko.length;e++)Ko[e]._workInProgressVersionPrimary=null;Ko.length=0}var Qo=x.ReactCurrentDispatcher,Xo=x.ReactCurrentBatchConfig,Jo=0,ei=null,ti=null,ni=null,ri=!1,ai=!1;function oi(){throw Error(i(321))}function ii(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!ur(e[n],t[n]))return!1;return!0}function si(e,t,n,r,a,o){if(Jo=o,ei=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,Qo.current=null===e||null===e.memoizedState?Oi:Ii,e=n(r,a),ai){o=0;do{if(ai=!1,!(25>o))throw Error(i(301));o+=1,ni=ti=null,t.updateQueue=null,Qo.current=Di,e=n(r,a)}while(ai)}if(Qo.current=Pi,t=null!==ti&&null!==ti.next,Jo=0,ni=ti=ei=null,ri=!1,t)throw Error(i(300));return e}function li(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===ni?ei.memoizedState=ni=e:ni=ni.next=e,ni}function ci(){if(null===ti){var e=ei.alternate;e=null!==e?e.memoizedState:null}else e=ti.next;var t=null===ni?ei.memoizedState:ni.next;if(null!==t)ni=t,ti=e;else{if(null===e)throw Error(i(310));e={memoizedState:(ti=e).memoizedState,baseState:ti.baseState,baseQueue:ti.baseQueue,queue:ti.queue,next:null},null===ni?ei.memoizedState=ni=e:ni=ni.next=e}return ni}function ui(e,t){return"function"==typeof t?t(e):t}function di(e){var t=ci(),n=t.queue;if(null===n)throw Error(i(311));n.lastRenderedReducer=e;var r=ti,a=r.baseQueue,o=n.pending;if(null!==o){if(null!==a){var s=a.next;a.next=o.next,o.next=s}r.baseQueue=a=o,n.pending=null}if(null!==a){a=a.next,r=r.baseState;var l=s=o=null,c=a;do{var u=c.lane;if((Jo&u)===u)null!==l&&(l=l.next={lane:0,action:c.action,eagerReducer:c.eagerReducer,eagerState:c.eagerState,next:null}),r=c.eagerReducer===e?c.eagerState:e(r,c.action);else{var d={lane:u,action:c.action,eagerReducer:c.eagerReducer,eagerState:c.eagerState,next:null};null===l?(s=l=d,o=r):l=l.next=d,ei.lanes|=u,Us|=u}c=c.next}while(null!==c&&c!==a);null===l?o=r:l.next=s,ur(r,t.memoizedState)||(Fi=!0),t.memoizedState=r,t.baseState=o,t.baseQueue=l,n.lastRenderedState=r}return[t.memoizedState,n.dispatch]}function fi(e){var t=ci(),n=t.queue;if(null===n)throw Error(i(311));n.lastRenderedReducer=e;var r=n.dispatch,a=n.pending,o=t.memoizedState;if(null!==a){n.pending=null;var s=a=a.next;do{o=e(o,s.action),s=s.next}while(s!==a);ur(o,t.memoizedState)||(Fi=!0),t.memoizedState=o,null===t.baseQueue&&(t.baseState=o),n.lastRenderedState=o}return[o,r]}function pi(e,t,n){var r=t._getVersion;r=r(t._source);var a=t._workInProgressVersionPrimary;if(null!==a?e=a===r:(e=e.mutableReadLanes,(e=(Jo&e)===e)&&(t._workInProgressVersionPrimary=r,Ko.push(t))),e)return n(t._source);throw Ko.push(t),Error(i(350))}function mi(e,t,n,r){var a=Os;if(null===a)throw Error(i(349));var o=t._getVersion,s=o(t._source),l=Qo.current,c=l.useState((function(){return pi(a,t,n)})),u=c[1],d=c[0];c=ni;var f=e.memoizedState,p=f.refs,m=p.getSnapshot,h=f.source;f=f.subscribe;var g=ei;return e.memoizedState={refs:p,source:t,subscribe:r},l.useEffect((function(){p.getSnapshot=n,p.setSnapshot=u;var e=o(t._source);if(!ur(s,e)){e=n(t._source),ur(d,e)||(u(e),e=pl(g),a.mutableReadLanes|=e&a.pendingLanes),e=a.mutableReadLanes,a.entangledLanes|=e;for(var r=a.entanglements,i=e;0<i;){var l=31-Ht(i),c=1<<l;r[l]|=e,i&=~c}}}),[n,t,r]),l.useEffect((function(){return r(t._source,(function(){var e=p.getSnapshot,n=p.setSnapshot;try{n(e(t._source));var r=pl(g);a.mutableReadLanes|=r&a.pendingLanes}catch(o){n((function(){throw o}))}}))}),[t,r]),ur(m,n)&&ur(h,t)&&ur(f,r)||((e={pending:null,dispatch:null,lastRenderedReducer:ui,lastRenderedState:d}).dispatch=u=Ni.bind(null,ei,e),c.queue=e,c.baseQueue=null,d=pi(a,t,n),c.memoizedState=c.baseState=d),d}function hi(e,t,n){return mi(ci(),e,t,n)}function gi(e){var t=li();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e=(e=t.queue={pending:null,dispatch:null,lastRenderedReducer:ui,lastRenderedState:e}).dispatch=Ni.bind(null,ei,e),[t.memoizedState,e]}function vi(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===(t=ei.updateQueue)?(t={lastEffect:null},ei.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(r=n.next,n.next=e,e.next=r,t.lastEffect=e),e}function bi(e){return e={current:e},li().memoizedState=e}function yi(){return ci().memoizedState}function wi(e,t,n,r){var a=li();ei.flags|=e,a.memoizedState=vi(1|t,n,void 0,void 0===r?null:r)}function xi(e,t,n,r){var a=ci();r=void 0===r?null:r;var o=void 0;if(null!==ti){var i=ti.memoizedState;if(o=i.destroy,null!==r&&ii(r,i.deps))return void vi(t,n,o,r)}ei.flags|=e,a.memoizedState=vi(1|t,n,o,r)}function ki(e,t){return wi(516,4,e,t)}function Ei(e,t){return xi(516,4,e,t)}function Si(e,t){return xi(4,2,e,t)}function _i(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function Ci(e,t,n){return n=null!=n?n.concat([e]):null,xi(4,2,_i.bind(null,t,e),n)}function Ti(){}function Ai(e,t){var n=ci();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&ii(t,r[1])?r[0]:(n.memoizedState=[e,t],e)}function Li(e,t){var n=ci();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&ii(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)}function Ri(e,t){var n=Ha();Za(98>n?98:n,(function(){e(!0)})),Za(97<n?97:n,(function(){var n=Xo.transition;Xo.transition=1;try{e(!1),t()}finally{Xo.transition=n}}))}function Ni(e,t,n){var r=fl(),a=pl(e),o={lane:a,action:n,eagerReducer:null,eagerState:null,next:null},i=t.pending;if(null===i?o.next=o:(o.next=i.next,i.next=o),t.pending=o,i=e.alternate,e===ei||null!==i&&i===ei)ai=ri=!0;else{if(0===e.lanes&&(null===i||0===i.lanes)&&null!==(i=t.lastRenderedReducer))try{var s=t.lastRenderedState,l=i(s,n);if(o.eagerReducer=i,o.eagerState=l,ur(l,s))return}catch(c){}ml(e,a,r)}}var Pi={readContext:io,useCallback:oi,useContext:oi,useEffect:oi,useImperativeHandle:oi,useLayoutEffect:oi,useMemo:oi,useReducer:oi,useRef:oi,useState:oi,useDebugValue:oi,useDeferredValue:oi,useTransition:oi,useMutableSource:oi,useOpaqueIdentifier:oi,unstable_isNewReconciler:!1},Oi={readContext:io,useCallback:function(e,t){return li().memoizedState=[e,void 0===t?null:t],e},useContext:io,useEffect:ki,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,wi(4,2,_i.bind(null,t,e),n)},useLayoutEffect:function(e,t){return wi(4,2,e,t)},useMemo:function(e,t){var n=li();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=li();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e=(e=r.queue={pending:null,dispatch:null,lastRenderedReducer:e,lastRenderedState:t}).dispatch=Ni.bind(null,ei,e),[r.memoizedState,e]},useRef:bi,useState:gi,useDebugValue:Ti,useDeferredValue:function(e){var t=gi(e),n=t[0],r=t[1];return ki((function(){var t=Xo.transition;Xo.transition=1;try{r(e)}finally{Xo.transition=t}}),[e]),n},useTransition:function(){var e=gi(!1),t=e[0];return bi(e=Ri.bind(null,e[1])),[e,t]},useMutableSource:function(e,t,n){var r=li();return r.memoizedState={refs:{getSnapshot:t,setSnapshot:null},source:e,subscribe:n},mi(r,e,t,n)},useOpaqueIdentifier:function(){if(qo){var e=!1,t=function(e){return{$$typeof:D,toString:e,valueOf:e}}((function(){throw e||(e=!0,n("r:"+(Yr++).toString(36))),Error(i(355))})),n=gi(t)[1];return 0==(2&ei.mode)&&(ei.flags|=516,vi(5,(function(){n("r:"+(Yr++).toString(36))}),void 0,null)),t}return gi(t="r:"+(Yr++).toString(36)),t},unstable_isNewReconciler:!1},Ii={readContext:io,useCallback:Ai,useContext:io,useEffect:Ei,useImperativeHandle:Ci,useLayoutEffect:Si,useMemo:Li,useReducer:di,useRef:yi,useState:function(){return di(ui)},useDebugValue:Ti,useDeferredValue:function(e){var t=di(ui),n=t[0],r=t[1];return Ei((function(){var t=Xo.transition;Xo.transition=1;try{r(e)}finally{Xo.transition=t}}),[e]),n},useTransition:function(){var e=di(ui)[0];return[yi().current,e]},useMutableSource:hi,useOpaqueIdentifier:function(){return di(ui)[0]},unstable_isNewReconciler:!1},Di={readContext:io,useCallback:Ai,useContext:io,useEffect:Ei,useImperativeHandle:Ci,useLayoutEffect:Si,useMemo:Li,useReducer:fi,useRef:yi,useState:function(){return fi(ui)},useDebugValue:Ti,useDeferredValue:function(e){var t=fi(ui),n=t[0],r=t[1];return Ei((function(){var t=Xo.transition;Xo.transition=1;try{r(e)}finally{Xo.transition=t}}),[e]),n},useTransition:function(){var e=fi(ui)[0];return[yi().current,e]},useMutableSource:hi,useOpaqueIdentifier:function(){return fi(ui)[0]},unstable_isNewReconciler:!1},Mi=x.ReactCurrentOwner,Fi=!1;function Bi(e,t,n,r){t.child=null===e?Ao(t,null,n,r):To(t,e.child,n,r)}function ji(e,t,n,r,a){n=n.render;var o=t.ref;return oo(t,a),r=si(e,t,n,r,o,a),null===e||Fi?(t.flags|=1,Bi(e,t,r,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~a,os(e,t,a))}function zi(e,t,n,r,a,o){if(null===e){var i=n.type;return"function"!=typeof i||Gl(i)||void 0!==i.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Vl(n.type,null,r,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=i,Ui(e,t,i,r,a,o))}return i=e.child,0==(a&o)&&(a=i.memoizedProps,(n=null!==(n=n.compare)?n:fr)(a,r)&&e.ref===t.ref)?os(e,t,o):(t.flags|=1,(e=Zl(i,r)).ref=t.ref,e.return=t,t.child=e)}function Ui(e,t,n,r,a,o){if(null!==e&&fr(e.memoizedProps,r)&&e.ref===t.ref){if(Fi=!1,0==(o&a))return t.lanes=e.lanes,os(e,t,o);0!=(16384&e.flags)&&(Fi=!0)}return Hi(e,t,n,r,o)}function qi(e,t,n){var r=t.pendingProps,a=r.children,o=null!==e?e.memoizedState:null;if("hidden"===r.mode||"unstable-defer-without-hiding"===r.mode)if(0==(4&t.mode))t.memoizedState={baseLanes:0},kl(t,n);else{if(0==(1073741824&n))return e=null!==o?o.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e},kl(t,e),null;t.memoizedState={baseLanes:0},kl(t,null!==o?o.baseLanes:n)}else null!==o?(r=o.baseLanes|n,t.memoizedState=null):r=n,kl(t,r);return Bi(e,t,a,n),t.child}function $i(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=128)}function Hi(e,t,n,r,a){var o=va(n)?ha:pa.current;return o=ga(t,o),oo(t,a),n=si(e,t,n,r,o,a),null===e||Fi?(t.flags|=1,Bi(e,t,n,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~a,os(e,t,a))}function Gi(e,t,n,r,a){if(va(n)){var o=!0;xa(t)}else o=!1;if(oo(t,a),null===t.stateNode)null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),wo(t,n,r),ko(t,n,r,a),r=!0;else if(null===e){var i=t.stateNode,s=t.memoizedProps;i.props=s;var l=i.context,c=n.contextType;"object"==typeof c&&null!==c?c=io(c):c=ga(t,c=va(n)?ha:pa.current);var u=n.getDerivedStateFromProps,d="function"==typeof u||"function"==typeof i.getSnapshotBeforeUpdate;d||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(s!==r||l!==c)&&xo(t,i,r,c),so=!1;var f=t.memoizedState;i.state=f,mo(t,r,i,a),l=t.memoizedState,s!==r||f!==l||ma.current||so?("function"==typeof u&&(vo(t,n,u,r),l=t.memoizedState),(s=so||yo(t,n,s,r,f,l,c))?(d||"function"!=typeof i.UNSAFE_componentWillMount&&"function"!=typeof i.componentWillMount||("function"==typeof i.componentWillMount&&i.componentWillMount(),"function"==typeof i.UNSAFE_componentWillMount&&i.UNSAFE_componentWillMount()),"function"==typeof i.componentDidMount&&(t.flags|=4)):("function"==typeof i.componentDidMount&&(t.flags|=4),t.memoizedProps=r,t.memoizedState=l),i.props=r,i.state=l,i.context=c,r=s):("function"==typeof i.componentDidMount&&(t.flags|=4),r=!1)}else{i=t.stateNode,co(e,t),s=t.memoizedProps,c=t.type===t.elementType?s:Qa(t.type,s),i.props=c,d=t.pendingProps,f=i.context,"object"==typeof(l=n.contextType)&&null!==l?l=io(l):l=ga(t,l=va(n)?ha:pa.current);var p=n.getDerivedStateFromProps;(u="function"==typeof p||"function"==typeof i.getSnapshotBeforeUpdate)||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(s!==d||f!==l)&&xo(t,i,r,l),so=!1,f=t.memoizedState,i.state=f,mo(t,r,i,a);var m=t.memoizedState;s!==d||f!==m||ma.current||so?("function"==typeof p&&(vo(t,n,p,r),m=t.memoizedState),(c=so||yo(t,n,c,r,f,m,l))?(u||"function"!=typeof i.UNSAFE_componentWillUpdate&&"function"!=typeof i.componentWillUpdate||("function"==typeof i.componentWillUpdate&&i.componentWillUpdate(r,m,l),"function"==typeof i.UNSAFE_componentWillUpdate&&i.UNSAFE_componentWillUpdate(r,m,l)),"function"==typeof i.componentDidUpdate&&(t.flags|=4),"function"==typeof i.getSnapshotBeforeUpdate&&(t.flags|=256)):("function"!=typeof i.componentDidUpdate||s===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||s===e.memoizedProps&&f===e.memoizedState||(t.flags|=256),t.memoizedProps=r,t.memoizedState=m),i.props=r,i.state=m,i.context=l,r=c):("function"!=typeof i.componentDidUpdate||s===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||s===e.memoizedProps&&f===e.memoizedState||(t.flags|=256),r=!1)}return Zi(e,t,n,r,o,a)}function Zi(e,t,n,r,a,o){$i(e,t);var i=0!=(64&t.flags);if(!r&&!i)return a&&ka(t,n,!1),os(e,t,o);r=t.stateNode,Mi.current=t;var s=i&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&i?(t.child=To(t,e.child,null,o),t.child=To(t,null,s,o)):Bi(e,t,s,o),t.memoizedState=r.state,a&&ka(t,n,!0),t.child}function Vi(e){var t=e.stateNode;t.pendingContext?ya(0,t.pendingContext,t.pendingContext!==t.context):t.context&&ya(0,t.context,!1),Io(e,t.containerInfo)}var Wi,Ki,Yi,Qi={dehydrated:null,retryLane:0};function Xi(e,t,n){var r,a=t.pendingProps,o=Bo.current,i=!1;return(r=0!=(64&t.flags))||(r=(null===e||null!==e.memoizedState)&&0!=(2&o)),r?(i=!0,t.flags&=-65):null!==e&&null===e.memoizedState||void 0===a.fallback||!0===a.unstable_avoidThisFallback||(o|=1),da(Bo,1&o),null===e?(void 0!==a.fallback&&Go(t),e=a.children,o=a.fallback,i?(e=Ji(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qi,e):"number"==typeof a.unstable_expectedLoadTime?(e=Ji(t,e,o,n),t.child.memoizedState={baseLanes:n},t.memoizedState=Qi,t.lanes=33554432,e):((n=Kl({mode:"visible",children:e},t.mode,n,null)).return=t,t.child=n)):(e.memoizedState,i?(a=ts(e,t,a.children,a.fallback,n),i=t.child,o=e.child.memoizedState,i.memoizedState=null===o?{baseLanes:n}:{baseLanes:o.baseLanes|n},i.childLanes=e.childLanes&~n,t.memoizedState=Qi,a):(n=es(e,t,a.children,n),t.memoizedState=null,n))}function Ji(e,t,n,r){var a=e.mode,o=e.child;return t={mode:"hidden",children:t},0==(2&a)&&null!==o?(o.childLanes=0,o.pendingProps=t):o=Kl(t,a,0,null),n=Wl(n,a,r,null),o.return=e,n.return=e,o.sibling=n,e.child=o,n}function es(e,t,n,r){var a=e.child;return e=a.sibling,n=Zl(a,{mode:"visible",children:n}),0==(2&t.mode)&&(n.lanes=r),n.return=t,n.sibling=null,null!==e&&(e.nextEffect=null,e.flags=8,t.firstEffect=t.lastEffect=e),t.child=n}function ts(e,t,n,r,a){var o=t.mode,i=e.child;e=i.sibling;var s={mode:"hidden",children:n};return 0==(2&o)&&t.child!==i?((n=t.child).childLanes=0,n.pendingProps=s,null!==(i=n.lastEffect)?(t.firstEffect=n.firstEffect,t.lastEffect=i,i.nextEffect=null):t.firstEffect=t.lastEffect=null):n=Zl(i,s),null!==e?r=Zl(e,r):(r=Wl(r,o,a,null)).flags|=2,r.return=t,n.return=t,n.sibling=r,t.child=n,r}function ns(e,t){e.lanes|=t;var n=e.alternate;null!==n&&(n.lanes|=t),ao(e.return,t)}function rs(e,t,n,r,a,o){var i=e.memoizedState;null===i?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:a,lastEffect:o}:(i.isBackwards=t,i.rendering=null,i.renderingStartTime=0,i.last=r,i.tail=n,i.tailMode=a,i.lastEffect=o)}function as(e,t,n){var r=t.pendingProps,a=r.revealOrder,o=r.tail;if(Bi(e,t,r.children,n),0!=(2&(r=Bo.current)))r=1&r|2,t.flags|=64;else{if(null!==e&&0!=(64&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&ns(e,n);else if(19===e.tag)ns(e,n);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(da(Bo,r),0==(2&t.mode))t.memoizedState=null;else switch(a){case"forwards":for(n=t.child,a=null;null!==n;)null!==(e=n.alternate)&&null===jo(e)&&(a=n),n=n.sibling;null===(n=a)?(a=t.child,t.child=null):(a=n.sibling,n.sibling=null),rs(t,!1,a,n,o,t.lastEffect);break;case"backwards":for(n=null,a=t.child,t.child=null;null!==a;){if(null!==(e=a.alternate)&&null===jo(e)){t.child=a;break}e=a.sibling,a.sibling=n,n=a,a=e}rs(t,!0,n,null,o,t.lastEffect);break;case"together":rs(t,!1,null,null,void 0,t.lastEffect);break;default:t.memoizedState=null}return t.child}function os(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Us|=t.lanes,0!=(n&t.childLanes)){if(null!==e&&t.child!==e.child)throw Error(i(153));if(null!==t.child){for(n=Zl(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Zl(e,e.pendingProps)).return=t;n.sibling=null}return t.child}return null}function is(e,t){if(!qo)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function ss(e,t,n){var r=t.pendingProps;switch(t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:case 17:return va(t.type)&&ba(),null;case 3:return Do(),ua(ma),ua(pa),Yo(),(r=t.stateNode).pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),null!==e&&null!==e.child||(Vo(t)?t.flags|=4:r.hydrate||(t.flags|=256)),null;case 5:Fo(t);var o=Oo(Po.current);if(n=t.type,null!==e&&null!=t.stateNode)Ki(e,t,n,r),e.ref!==t.ref&&(t.flags|=128);else{if(!r){if(null===t.stateNode)throw Error(i(166));return null}if(e=Oo(Ro.current),Vo(t)){r=t.stateNode,n=t.type;var s=t.memoizedProps;switch(r[Xr]=t,r[Jr]=s,n){case"dialog":Rr("cancel",r),Rr("close",r);break;case"iframe":case"object":case"embed":Rr("load",r);break;case"video":case"audio":for(e=0;e<Cr.length;e++)Rr(Cr[e],r);break;case"source":Rr("error",r);break;case"img":case"image":case"link":Rr("error",r),Rr("load",r);break;case"details":Rr("toggle",r);break;case"input":ee(r,s),Rr("invalid",r);break;case"select":r._wrapperState={wasMultiple:!!s.multiple},Rr("invalid",r);break;case"textarea":le(r,s),Rr("invalid",r)}for(var c in Se(n,s),e=null,s)s.hasOwnProperty(c)&&(o=s[c],"children"===c?"string"==typeof o?r.textContent!==o&&(e=["children",o]):"number"==typeof o&&r.textContent!==""+o&&(e=["children",""+o]):l.hasOwnProperty(c)&&null!=o&&"onScroll"===c&&Rr("scroll",r));switch(n){case"input":Y(r),re(r,s,!0);break;case"textarea":Y(r),ue(r);break;case"select":case"option":break;default:"function"==typeof s.onClick&&(r.onclick=zr)}r=e,t.updateQueue=r,null!==r&&(t.flags|=4)}else{switch(c=9===o.nodeType?o:o.ownerDocument,e===de&&(e=pe(n)),e===de?"script"===n?((e=c.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=c.createElement(n,{is:r.is}):(e=c.createElement(n),"select"===n&&(c=e,r.multiple?c.multiple=!0:r.size&&(c.size=r.size))):e=c.createElementNS(e,n),e[Xr]=t,e[Jr]=r,Wi(e,t),t.stateNode=e,c=_e(n,r),n){case"dialog":Rr("cancel",e),Rr("close",e),o=r;break;case"iframe":case"object":case"embed":Rr("load",e),o=r;break;case"video":case"audio":for(o=0;o<Cr.length;o++)Rr(Cr[o],e);o=r;break;case"source":Rr("error",e),o=r;break;case"img":case"image":case"link":Rr("error",e),Rr("load",e),o=r;break;case"details":Rr("toggle",e),o=r;break;case"input":ee(e,r),o=J(e,r),Rr("invalid",e);break;case"option":o=oe(e,r);break;case"select":e._wrapperState={wasMultiple:!!r.multiple},o=a({},r,{value:void 0}),Rr("invalid",e);break;case"textarea":le(e,r),o=se(e,r),Rr("invalid",e);break;default:o=r}Se(n,o);var u=o;for(s in u)if(u.hasOwnProperty(s)){var d=u[s];"style"===s?ke(e,d):"dangerouslySetInnerHTML"===s?null!=(d=d?d.__html:void 0)&&ve(e,d):"children"===s?"string"==typeof d?("textarea"!==n||""!==d)&&be(e,d):"number"==typeof d&&be(e,""+d):"suppressContentEditableWarning"!==s&&"suppressHydrationWarning"!==s&&"autoFocus"!==s&&(l.hasOwnProperty(s)?null!=d&&"onScroll"===s&&Rr("scroll",e):null!=d&&w(e,s,d,c))}switch(n){case"input":Y(e),re(e,r,!1);break;case"textarea":Y(e),ue(e);break;case"option":null!=r.value&&e.setAttribute("value",""+W(r.value));break;case"select":e.multiple=!!r.multiple,null!=(s=r.value)?ie(e,!!r.multiple,s,!1):null!=r.defaultValue&&ie(e,!!r.multiple,r.defaultValue,!0);break;default:"function"==typeof o.onClick&&(e.onclick=zr)}$r(n,r)&&(t.flags|=4)}null!==t.ref&&(t.flags|=128)}return null;case 6:if(e&&null!=t.stateNode)Yi(0,t,e.memoizedProps,r);else{if("string"!=typeof r&&null===t.stateNode)throw Error(i(166));n=Oo(Po.current),Oo(Ro.current),Vo(t)?(r=t.stateNode,n=t.memoizedProps,r[Xr]=t,r.nodeValue!==n&&(t.flags|=4)):((r=(9===n.nodeType?n:n.ownerDocument).createTextNode(r))[Xr]=t,t.stateNode=r)}return null;case 13:return ua(Bo),r=t.memoizedState,0!=(64&t.flags)?(t.lanes=n,t):(r=null!==r,n=!1,null===e?void 0!==t.memoizedProps.fallback&&Vo(t):n=null!==e.memoizedState,r&&!n&&0!=(2&t.mode)&&(null===e&&!0!==t.memoizedProps.unstable_avoidThisFallback||0!=(1&Bo.current)?0===Bs&&(Bs=3):(0!==Bs&&3!==Bs||(Bs=4),null===Os||0==(134217727&Us)&&0==(134217727&qs)||bl(Os,Ds))),(r||n)&&(t.flags|=4),null);case 4:return Do(),null===e&&Pr(t.stateNode.containerInfo),null;case 10:return ro(t),null;case 19:if(ua(Bo),null===(r=t.memoizedState))return null;if(s=0!=(64&t.flags),null===(c=r.rendering))if(s)is(r,!1);else{if(0!==Bs||null!==e&&0!=(64&e.flags))for(e=t.child;null!==e;){if(null!==(c=jo(e))){for(t.flags|=64,is(r,!1),null!==(s=c.updateQueue)&&(t.updateQueue=s,t.flags|=4),null===r.lastEffect&&(t.firstEffect=null),t.lastEffect=r.lastEffect,r=n,n=t.child;null!==n;)e=r,(s=n).flags&=2,s.nextEffect=null,s.firstEffect=null,s.lastEffect=null,null===(c=s.alternate)?(s.childLanes=0,s.lanes=e,s.child=null,s.memoizedProps=null,s.memoizedState=null,s.updateQueue=null,s.dependencies=null,s.stateNode=null):(s.childLanes=c.childLanes,s.lanes=c.lanes,s.child=c.child,s.memoizedProps=c.memoizedProps,s.memoizedState=c.memoizedState,s.updateQueue=c.updateQueue,s.type=c.type,e=c.dependencies,s.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return da(Bo,1&Bo.current|2),t.child}e=e.sibling}null!==r.tail&&$a()>Zs&&(t.flags|=64,s=!0,is(r,!1),t.lanes=33554432)}else{if(!s)if(null!==(e=jo(c))){if(t.flags|=64,s=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),is(r,!0),null===r.tail&&"hidden"===r.tailMode&&!c.alternate&&!qo)return null!==(t=t.lastEffect=r.lastEffect)&&(t.nextEffect=null),null}else 2*$a()-r.renderingStartTime>Zs&&1073741824!==n&&(t.flags|=64,s=!0,is(r,!1),t.lanes=33554432);r.isBackwards?(c.sibling=t.child,t.child=c):(null!==(n=r.last)?n.sibling=c:t.child=c,r.last=c)}return null!==r.tail?(n=r.tail,r.rendering=n,r.tail=n.sibling,r.lastEffect=t.lastEffect,r.renderingStartTime=$a(),n.sibling=null,t=Bo.current,da(Bo,s?1&t|2:1&t),n):null;case 23:case 24:return El(),null!==e&&null!==e.memoizedState!=(null!==t.memoizedState)&&"unstable-defer-without-hiding"!==r.mode&&(t.flags|=4),null}throw Error(i(156,t.tag))}function ls(e){switch(e.tag){case 1:va(e.type)&&ba();var t=e.flags;return 4096&t?(e.flags=-4097&t|64,e):null;case 3:if(Do(),ua(ma),ua(pa),Yo(),0!=(64&(t=e.flags)))throw Error(i(285));return e.flags=-4097&t|64,e;case 5:return Fo(e),null;case 13:return ua(Bo),4096&(t=e.flags)?(e.flags=-4097&t|64,e):null;case 19:return ua(Bo),null;case 4:return Do(),null;case 10:return ro(e),null;case 23:case 24:return El(),null;default:return null}}function cs(e,t){try{var n="",r=t;do{n+=Z(r),r=r.return}while(r);var a=n}catch(o){a="\nError generating stack: "+o.message+"\n"+o.stack}return{value:e,source:t,stack:a}}function us(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}Wi=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Ki=function(e,t,n,r){var o=e.memoizedProps;if(o!==r){e=t.stateNode,Oo(Ro.current);var i,s=null;switch(n){case"input":o=J(e,o),r=J(e,r),s=[];break;case"option":o=oe(e,o),r=oe(e,r),s=[];break;case"select":o=a({},o,{value:void 0}),r=a({},r,{value:void 0}),s=[];break;case"textarea":o=se(e,o),r=se(e,r),s=[];break;default:"function"!=typeof o.onClick&&"function"==typeof r.onClick&&(e.onclick=zr)}for(d in Se(n,r),n=null,o)if(!r.hasOwnProperty(d)&&o.hasOwnProperty(d)&&null!=o[d])if("style"===d){var c=o[d];for(i in c)c.hasOwnProperty(i)&&(n||(n={}),n[i]="")}else"dangerouslySetInnerHTML"!==d&&"children"!==d&&"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&"autoFocus"!==d&&(l.hasOwnProperty(d)?s||(s=[]):(s=s||[]).push(d,null));for(d in r){var u=r[d];if(c=null!=o?o[d]:void 0,r.hasOwnProperty(d)&&u!==c&&(null!=u||null!=c))if("style"===d)if(c){for(i in c)!c.hasOwnProperty(i)||u&&u.hasOwnProperty(i)||(n||(n={}),n[i]="");for(i in u)u.hasOwnProperty(i)&&c[i]!==u[i]&&(n||(n={}),n[i]=u[i])}else n||(s||(s=[]),s.push(d,n)),n=u;else"dangerouslySetInnerHTML"===d?(u=u?u.__html:void 0,c=c?c.__html:void 0,null!=u&&c!==u&&(s=s||[]).push(d,u)):"children"===d?"string"!=typeof u&&"number"!=typeof u||(s=s||[]).push(d,""+u):"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&(l.hasOwnProperty(d)?(null!=u&&"onScroll"===d&&Rr("scroll",e),s||c===u||(s=[])):"object"==typeof u&&null!==u&&u.$$typeof===D?u.toString():(s=s||[]).push(d,u))}n&&(s=s||[]).push("style",n);var d=s;(t.updateQueue=d)&&(t.flags|=4)}},Yi=function(e,t,n,r){n!==r&&(t.flags|=4)};var ds="function"==typeof WeakMap?WeakMap:Map;function fs(e,t,n){(n=uo(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){Ys||(Ys=!0,Qs=r),us(0,t)},n}function ps(e,t,n){(n=uo(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var a=t.value;n.payload=function(){return us(0,t),r(a)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){"function"!=typeof r&&(null===Xs?Xs=new Set([this]):Xs.add(this),us(0,t));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}var ms="function"==typeof WeakSet?WeakSet:Set;function hs(e){var t=e.ref;if(null!==t)if("function"==typeof t)try{t(null)}catch(n){zl(e,n)}else t.current=null}function gs(e,t){switch(t.tag){case 0:case 11:case 15:case 22:case 5:case 6:case 4:case 17:return;case 1:if(256&t.flags&&null!==e){var n=e.memoizedProps,r=e.memoizedState;t=(e=t.stateNode).getSnapshotBeforeUpdate(t.elementType===t.type?n:Qa(t.type,n),r),e.__reactInternalSnapshotBeforeUpdate=t}return;case 3:return void(256&t.flags&&Vr(t.stateNode.containerInfo))}throw Error(i(163))}function vs(e,t,n){switch(n.tag){case 0:case 11:case 15:case 22:if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{if(3==(3&e.tag)){var r=e.create;e.destroy=r()}e=e.next}while(e!==t)}if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{var a=e;r=a.next,0!=(4&(a=a.tag))&&0!=(1&a)&&(Fl(n,e),Ml(n,e)),e=r}while(e!==t)}return;case 1:return e=n.stateNode,4&n.flags&&(null===t?e.componentDidMount():(r=n.elementType===n.type?t.memoizedProps:Qa(n.type,t.memoizedProps),e.componentDidUpdate(r,t.memoizedState,e.__reactInternalSnapshotBeforeUpdate))),void(null!==(t=n.updateQueue)&&ho(n,t,e));case 3:if(null!==(t=n.updateQueue)){if(e=null,null!==n.child)switch(n.child.tag){case 5:case 1:e=n.child.stateNode}ho(n,t,e)}return;case 5:return e=n.stateNode,void(null===t&&4&n.flags&&$r(n.type,n.memoizedProps)&&e.focus());case 6:case 4:case 12:case 19:case 17:case 20:case 21:case 23:case 24:return;case 13:return void(null===n.memoizedState&&(n=n.alternate,null!==n&&(n=n.memoizedState,null!==n&&(n=n.dehydrated,null!==n&&kt(n)))))}throw Error(i(163))}function bs(e,t){for(var n=e;;){if(5===n.tag){var r=n.stateNode;if(t)"function"==typeof(r=r.style).setProperty?r.setProperty("display","none","important"):r.display="none";else{r=n.stateNode;var a=n.memoizedProps.style;a=null!=a&&a.hasOwnProperty("display")?a.display:null,r.style.display=xe("display",a)}}else if(6===n.tag)n.stateNode.nodeValue=t?"":n.memoizedProps;else if((23!==n.tag&&24!==n.tag||null===n.memoizedState||n===e)&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===e)break;for(;null===n.sibling;){if(null===n.return||n.return===e)return;n=n.return}n.sibling.return=n.return,n=n.sibling}}function ys(e,t){if(Sa&&"function"==typeof Sa.onCommitFiberUnmount)try{Sa.onCommitFiberUnmount(Ea,t)}catch(o){}switch(t.tag){case 0:case 11:case 14:case 15:case 22:if(null!==(e=t.updateQueue)&&null!==(e=e.lastEffect)){var n=e=e.next;do{var r=n,a=r.destroy;if(r=r.tag,void 0!==a)if(0!=(4&r))Fl(t,n);else{r=t;try{a()}catch(o){zl(r,o)}}n=n.next}while(n!==e)}break;case 1:if(hs(t),"function"==typeof(e=t.stateNode).componentWillUnmount)try{e.props=t.memoizedProps,e.state=t.memoizedState,e.componentWillUnmount()}catch(o){zl(t,o)}break;case 5:hs(t);break;case 4:_s(e,t)}}function ws(e){e.alternate=null,e.child=null,e.dependencies=null,e.firstEffect=null,e.lastEffect=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.return=null,e.updateQueue=null}function xs(e){return 5===e.tag||3===e.tag||4===e.tag}function ks(e){e:{for(var t=e.return;null!==t;){if(xs(t))break e;t=t.return}throw Error(i(160))}var n=t;switch(t=n.stateNode,n.tag){case 5:var r=!1;break;case 3:case 4:t=t.containerInfo,r=!0;break;default:throw Error(i(161))}16&n.flags&&(be(t,""),n.flags&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||xs(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag&&18!==n.tag;){if(2&n.flags)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.flags)){n=n.stateNode;break e}}r?Es(e,n,t):Ss(e,n,t)}function Es(e,t,n){var r=e.tag,a=5===r||6===r;if(a)e=a?e.stateNode:e.stateNode.instance,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=zr));else if(4!==r&&null!==(e=e.child))for(Es(e,t,n),e=e.sibling;null!==e;)Es(e,t,n),e=e.sibling}function Ss(e,t,n){var r=e.tag,a=5===r||6===r;if(a)e=a?e.stateNode:e.stateNode.instance,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&null!==(e=e.child))for(Ss(e,t,n),e=e.sibling;null!==e;)Ss(e,t,n),e=e.sibling}function _s(e,t){for(var n,r,a=t,o=!1;;){if(!o){o=a.return;e:for(;;){if(null===o)throw Error(i(160));switch(n=o.stateNode,o.tag){case 5:r=!1;break e;case 3:case 4:n=n.containerInfo,r=!0;break e}o=o.return}o=!0}if(5===a.tag||6===a.tag){e:for(var s=e,l=a,c=l;;)if(ys(s,c),null!==c.child&&4!==c.tag)c.child.return=c,c=c.child;else{if(c===l)break e;for(;null===c.sibling;){if(null===c.return||c.return===l)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}r?(s=n,l=a.stateNode,8===s.nodeType?s.parentNode.removeChild(l):s.removeChild(l)):n.removeChild(a.stateNode)}else if(4===a.tag){if(null!==a.child){n=a.stateNode.containerInfo,r=!0,a.child.return=a,a=a.child;continue}}else if(ys(e,a),null!==a.child){a.child.return=a,a=a.child;continue}if(a===t)break;for(;null===a.sibling;){if(null===a.return||a.return===t)return;4===(a=a.return).tag&&(o=!1)}a.sibling.return=a.return,a=a.sibling}}function Cs(e,t){switch(t.tag){case 0:case 11:case 14:case 15:case 22:var n=t.updateQueue;if(null!==(n=null!==n?n.lastEffect:null)){var r=n=n.next;do{3==(3&r.tag)&&(e=r.destroy,r.destroy=void 0,void 0!==e&&e()),r=r.next}while(r!==n)}return;case 1:case 12:case 17:return;case 5:if(null!=(n=t.stateNode)){r=t.memoizedProps;var a=null!==e?e.memoizedProps:r;e=t.type;var o=t.updateQueue;if(t.updateQueue=null,null!==o){for(n[Jr]=r,"input"===e&&"radio"===r.type&&null!=r.name&&te(n,r),_e(e,a),t=_e(e,r),a=0;a<o.length;a+=2){var s=o[a],l=o[a+1];"style"===s?ke(n,l):"dangerouslySetInnerHTML"===s?ve(n,l):"children"===s?be(n,l):w(n,s,l,t)}switch(e){case"input":ne(n,r);break;case"textarea":ce(n,r);break;case"select":e=n._wrapperState.wasMultiple,n._wrapperState.wasMultiple=!!r.multiple,null!=(o=r.value)?ie(n,!!r.multiple,o,!1):e!==!!r.multiple&&(null!=r.defaultValue?ie(n,!!r.multiple,r.defaultValue,!0):ie(n,!!r.multiple,r.multiple?[]:"",!1))}}}return;case 6:if(null===t.stateNode)throw Error(i(162));return void(t.stateNode.nodeValue=t.memoizedProps);case 3:return void((n=t.stateNode).hydrate&&(n.hydrate=!1,kt(n.containerInfo)));case 13:return null!==t.memoizedState&&(Gs=$a(),bs(t.child,!0)),void Ts(t);case 19:return void Ts(t);case 23:case 24:return void bs(t,null!==t.memoizedState)}throw Error(i(163))}function Ts(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new ms),t.forEach((function(t){var r=ql.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))}))}}function As(e,t){return null!==e&&(null===(e=e.memoizedState)||null!==e.dehydrated)&&(null!==(t=t.memoizedState)&&null===t.dehydrated)}var Ls=Math.ceil,Rs=x.ReactCurrentDispatcher,Ns=x.ReactCurrentOwner,Ps=0,Os=null,Is=null,Ds=0,Ms=0,Fs=ca(0),Bs=0,js=null,zs=0,Us=0,qs=0,$s=0,Hs=null,Gs=0,Zs=1/0;function Vs(){Zs=$a()+500}var Ws,Ks=null,Ys=!1,Qs=null,Xs=null,Js=!1,el=null,tl=90,nl=[],rl=[],al=null,ol=0,il=null,sl=-1,ll=0,cl=0,ul=null,dl=!1;function fl(){return 0!=(48&Ps)?$a():-1!==sl?sl:sl=$a()}function pl(e){if(0==(2&(e=e.mode)))return 1;if(0==(4&e))return 99===Ha()?1:2;if(0===ll&&(ll=zs),0!==Ya.transition){0!==cl&&(cl=null!==Hs?Hs.pendingLanes:0),e=ll;var t=4186112&~cl;return 0===(t&=-t)&&(0===(t=(e=4186112&~e)&-e)&&(t=8192)),t}return e=Ha(),0!=(4&Ps)&&98===e?e=zt(12,ll):e=zt(e=function(e){switch(e){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}(e),ll),e}function ml(e,t,n){if(50<ol)throw ol=0,il=null,Error(i(185));if(null===(e=hl(e,t)))return null;$t(e,t,n),e===Os&&(qs|=t,4===Bs&&bl(e,Ds));var r=Ha();1===t?0!=(8&Ps)&&0==(48&Ps)?yl(e):(gl(e,n),0===Ps&&(Vs(),Wa())):(0==(4&Ps)||98!==r&&99!==r||(null===al?al=new Set([e]):al.add(e)),gl(e,n)),Hs=e}function hl(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}function gl(e,t){for(var n=e.callbackNode,r=e.suspendedLanes,a=e.pingedLanes,o=e.expirationTimes,s=e.pendingLanes;0<s;){var l=31-Ht(s),c=1<<l,u=o[l];if(-1===u){if(0==(c&r)||0!=(c&a)){u=t,Ft(c);var d=Mt;o[l]=10<=d?u+250:6<=d?u+5e3:-1}}else u<=t&&(e.expiredLanes|=c);s&=~c}if(r=Bt(e,e===Os?Ds:0),t=Mt,0===r)null!==n&&(n!==Fa&&Ta(n),e.callbackNode=null,e.callbackPriority=0);else{if(null!==n){if(e.callbackPriority===t)return;n!==Fa&&Ta(n)}15===t?(n=yl.bind(null,e),null===ja?(ja=[n],za=Ca(Pa,Ka)):ja.push(n),n=Fa):14===t?n=Va(99,yl.bind(null,e)):(n=function(e){switch(e){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(i(358,e))}}(t),n=Va(n,vl.bind(null,e))),e.callbackPriority=t,e.callbackNode=n}}function vl(e){if(sl=-1,cl=ll=0,0!=(48&Ps))throw Error(i(327));var t=e.callbackNode;if(Dl()&&e.callbackNode!==t)return null;var n=Bt(e,e===Os?Ds:0);if(0===n)return null;var r=n,a=Ps;Ps|=16;var o=Cl();for(Os===e&&Ds===r||(Vs(),Sl(e,r));;)try{Ll();break}catch(l){_l(e,l)}if(no(),Rs.current=o,Ps=a,null!==Is?r=0:(Os=null,Ds=0,r=Bs),0!=(zs&qs))Sl(e,0);else if(0!==r){if(2===r&&(Ps|=64,e.hydrate&&(e.hydrate=!1,Vr(e.containerInfo)),0!==(n=jt(e))&&(r=Tl(e,n))),1===r)throw t=js,Sl(e,0),bl(e,n),gl(e,$a()),t;switch(e.finishedWork=e.current.alternate,e.finishedLanes=n,r){case 0:case 1:throw Error(i(345));case 2:case 5:Pl(e);break;case 3:if(bl(e,n),(62914560&n)===n&&10<(r=Gs+500-$a())){if(0!==Bt(e,0))break;if(((a=e.suspendedLanes)&n)!==n){fl(),e.pingedLanes|=e.suspendedLanes&a;break}e.timeoutHandle=Gr(Pl.bind(null,e),r);break}Pl(e);break;case 4:if(bl(e,n),(4186112&n)===n)break;for(r=e.eventTimes,a=-1;0<n;){var s=31-Ht(n);o=1<<s,(s=r[s])>a&&(a=s),n&=~o}if(n=a,10<(n=(120>(n=$a()-n)?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Ls(n/1960))-n)){e.timeoutHandle=Gr(Pl.bind(null,e),n);break}Pl(e);break;default:throw Error(i(329))}}return gl(e,$a()),e.callbackNode===t?vl.bind(null,e):null}function bl(e,t){for(t&=~$s,t&=~qs,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-Ht(t),r=1<<n;e[n]=-1,t&=~r}}function yl(e){if(0!=(48&Ps))throw Error(i(327));if(Dl(),e===Os&&0!=(e.expiredLanes&Ds)){var t=Ds,n=Tl(e,t);0!=(zs&qs)&&(n=Tl(e,t=Bt(e,t)))}else n=Tl(e,t=Bt(e,0));if(0!==e.tag&&2===n&&(Ps|=64,e.hydrate&&(e.hydrate=!1,Vr(e.containerInfo)),0!==(t=jt(e))&&(n=Tl(e,t))),1===n)throw n=js,Sl(e,0),bl(e,t),gl(e,$a()),n;return e.finishedWork=e.current.alternate,e.finishedLanes=t,Pl(e),gl(e,$a()),null}function wl(e,t){var n=Ps;Ps|=1;try{return e(t)}finally{0===(Ps=n)&&(Vs(),Wa())}}function xl(e,t){var n=Ps;Ps&=-2,Ps|=8;try{return e(t)}finally{0===(Ps=n)&&(Vs(),Wa())}}function kl(e,t){da(Fs,Ms),Ms|=t,zs|=t}function El(){Ms=Fs.current,ua(Fs)}function Sl(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,Zr(n)),null!==Is)for(n=Is.return;null!==n;){var r=n;switch(r.tag){case 1:null!=(r=r.type.childContextTypes)&&ba();break;case 3:Do(),ua(ma),ua(pa),Yo();break;case 5:Fo(r);break;case 4:Do();break;case 13:case 19:ua(Bo);break;case 10:ro(r);break;case 23:case 24:El()}n=n.return}Os=e,Is=Zl(e.current,null),Ds=Ms=zs=t,Bs=0,js=null,$s=qs=Us=0}function _l(e,t){for(;;){var n=Is;try{if(no(),Qo.current=Pi,ri){for(var r=ei.memoizedState;null!==r;){var a=r.queue;null!==a&&(a.pending=null),r=r.next}ri=!1}if(Jo=0,ni=ti=ei=null,ai=!1,Ns.current=null,null===n||null===n.return){Bs=1,js=t,Is=null;break}e:{var o=e,i=n.return,s=n,l=t;if(t=Ds,s.flags|=2048,s.firstEffect=s.lastEffect=null,null!==l&&"object"==typeof l&&"function"==typeof l.then){var c=l;if(0==(2&s.mode)){var u=s.alternate;u?(s.updateQueue=u.updateQueue,s.memoizedState=u.memoizedState,s.lanes=u.lanes):(s.updateQueue=null,s.memoizedState=null)}var d=0!=(1&Bo.current),f=i;do{var p;if(p=13===f.tag){var m=f.memoizedState;if(null!==m)p=null!==m.dehydrated;else{var h=f.memoizedProps;p=void 0!==h.fallback&&(!0!==h.unstable_avoidThisFallback||!d)}}if(p){var g=f.updateQueue;if(null===g){var v=new Set;v.add(c),f.updateQueue=v}else g.add(c);if(0==(2&f.mode)){if(f.flags|=64,s.flags|=16384,s.flags&=-2981,1===s.tag)if(null===s.alternate)s.tag=17;else{var b=uo(-1,1);b.tag=2,fo(s,b)}s.lanes|=1;break e}l=void 0,s=t;var y=o.pingCache;if(null===y?(y=o.pingCache=new ds,l=new Set,y.set(c,l)):void 0===(l=y.get(c))&&(l=new Set,y.set(c,l)),!l.has(s)){l.add(s);var w=Ul.bind(null,o,c,s);c.then(w,w)}f.flags|=4096,f.lanes=t;break e}f=f.return}while(null!==f);l=Error((V(s.type)||"A React component")+" suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.")}5!==Bs&&(Bs=2),l=cs(l,s),f=i;do{switch(f.tag){case 3:o=l,f.flags|=4096,t&=-t,f.lanes|=t,po(f,fs(0,o,t));break e;case 1:o=l;var x=f.type,k=f.stateNode;if(0==(64&f.flags)&&("function"==typeof x.getDerivedStateFromError||null!==k&&"function"==typeof k.componentDidCatch&&(null===Xs||!Xs.has(k)))){f.flags|=4096,t&=-t,f.lanes|=t,po(f,ps(f,o,t));break e}}f=f.return}while(null!==f)}Nl(n)}catch(E){t=E,Is===n&&null!==n&&(Is=n=n.return);continue}break}}function Cl(){var e=Rs.current;return Rs.current=Pi,null===e?Pi:e}function Tl(e,t){var n=Ps;Ps|=16;var r=Cl();for(Os===e&&Ds===t||Sl(e,t);;)try{Al();break}catch(a){_l(e,a)}if(no(),Ps=n,Rs.current=r,null!==Is)throw Error(i(261));return Os=null,Ds=0,Bs}function Al(){for(;null!==Is;)Rl(Is)}function Ll(){for(;null!==Is&&!Aa();)Rl(Is)}function Rl(e){var t=Ws(e.alternate,e,Ms);e.memoizedProps=e.pendingProps,null===t?Nl(e):Is=t,Ns.current=null}function Nl(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(2048&t.flags)){if(null!==(n=ss(n,t,Ms)))return void(Is=n);if(24!==(n=t).tag&&23!==n.tag||null===n.memoizedState||0!=(1073741824&Ms)||0==(4&n.mode)){for(var r=0,a=n.child;null!==a;)r|=a.lanes|a.childLanes,a=a.sibling;n.childLanes=r}null!==e&&0==(2048&e.flags)&&(null===e.firstEffect&&(e.firstEffect=t.firstEffect),null!==t.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=t.firstEffect),e.lastEffect=t.lastEffect),1<t.flags&&(null!==e.lastEffect?e.lastEffect.nextEffect=t:e.firstEffect=t,e.lastEffect=t))}else{if(null!==(n=ls(t)))return n.flags&=2047,void(Is=n);null!==e&&(e.firstEffect=e.lastEffect=null,e.flags|=2048)}if(null!==(t=t.sibling))return void(Is=t);Is=t=e}while(null!==t);0===Bs&&(Bs=5)}function Pl(e){var t=Ha();return Za(99,Ol.bind(null,e,t)),null}function Ol(e,t){do{Dl()}while(null!==el);if(0!=(48&Ps))throw Error(i(327));var n=e.finishedWork;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(i(177));e.callbackNode=null;var r=n.lanes|n.childLanes,a=r,o=e.pendingLanes&~a;e.pendingLanes=a,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=a,e.mutableReadLanes&=a,e.entangledLanes&=a,a=e.entanglements;for(var s=e.eventTimes,l=e.expirationTimes;0<o;){var c=31-Ht(o),u=1<<c;a[c]=0,s[c]=-1,l[c]=-1,o&=~u}if(null!==al&&0==(24&r)&&al.has(e)&&al.delete(e),e===Os&&(Is=Os=null,Ds=0),1<n.flags?null!==n.lastEffect?(n.lastEffect.nextEffect=n,r=n.firstEffect):r=n:r=n.firstEffect,null!==r){if(a=Ps,Ps|=32,Ns.current=null,Ur=Kt,vr(s=gr())){if("selectionStart"in s)l={start:s.selectionStart,end:s.selectionEnd};else e:if(l=(l=s.ownerDocument)&&l.defaultView||window,(u=l.getSelection&&l.getSelection())&&0!==u.rangeCount){l=u.anchorNode,o=u.anchorOffset,c=u.focusNode,u=u.focusOffset;try{l.nodeType,c.nodeType}catch(C){l=null;break e}var d=0,f=-1,p=-1,m=0,h=0,g=s,v=null;t:for(;;){for(var b;g!==l||0!==o&&3!==g.nodeType||(f=d+o),g!==c||0!==u&&3!==g.nodeType||(p=d+u),3===g.nodeType&&(d+=g.nodeValue.length),null!==(b=g.firstChild);)v=g,g=b;for(;;){if(g===s)break t;if(v===l&&++m===o&&(f=d),v===c&&++h===u&&(p=d),null!==(b=g.nextSibling))break;v=(g=v).parentNode}g=b}l=-1===f||-1===p?null:{start:f,end:p}}else l=null;l=l||{start:0,end:0}}else l=null;qr={focusedElem:s,selectionRange:l},Kt=!1,ul=null,dl=!1,Ks=r;do{try{Il()}catch(C){if(null===Ks)throw Error(i(330));zl(Ks,C),Ks=Ks.nextEffect}}while(null!==Ks);ul=null,Ks=r;do{try{for(s=e;null!==Ks;){var y=Ks.flags;if(16&y&&be(Ks.stateNode,""),128&y){var w=Ks.alternate;if(null!==w){var x=w.ref;null!==x&&("function"==typeof x?x(null):x.current=null)}}switch(1038&y){case 2:ks(Ks),Ks.flags&=-3;break;case 6:ks(Ks),Ks.flags&=-3,Cs(Ks.alternate,Ks);break;case 1024:Ks.flags&=-1025;break;case 1028:Ks.flags&=-1025,Cs(Ks.alternate,Ks);break;case 4:Cs(Ks.alternate,Ks);break;case 8:_s(s,l=Ks);var k=l.alternate;ws(l),null!==k&&ws(k)}Ks=Ks.nextEffect}}catch(C){if(null===Ks)throw Error(i(330));zl(Ks,C),Ks=Ks.nextEffect}}while(null!==Ks);if(x=qr,w=gr(),y=x.focusedElem,s=x.selectionRange,w!==y&&y&&y.ownerDocument&&hr(y.ownerDocument.documentElement,y)){null!==s&&vr(y)&&(w=s.start,void 0===(x=s.end)&&(x=w),"selectionStart"in y?(y.selectionStart=w,y.selectionEnd=Math.min(x,y.value.length)):(x=(w=y.ownerDocument||document)&&w.defaultView||window).getSelection&&(x=x.getSelection(),l=y.textContent.length,k=Math.min(s.start,l),s=void 0===s.end?k:Math.min(s.end,l),!x.extend&&k>s&&(l=s,s=k,k=l),l=mr(y,k),o=mr(y,s),l&&o&&(1!==x.rangeCount||x.anchorNode!==l.node||x.anchorOffset!==l.offset||x.focusNode!==o.node||x.focusOffset!==o.offset)&&((w=w.createRange()).setStart(l.node,l.offset),x.removeAllRanges(),k>s?(x.addRange(w),x.extend(o.node,o.offset)):(w.setEnd(o.node,o.offset),x.addRange(w))))),w=[];for(x=y;x=x.parentNode;)1===x.nodeType&&w.push({element:x,left:x.scrollLeft,top:x.scrollTop});for("function"==typeof y.focus&&y.focus(),y=0;y<w.length;y++)(x=w[y]).element.scrollLeft=x.left,x.element.scrollTop=x.top}Kt=!!Ur,qr=Ur=null,e.current=n,Ks=r;do{try{for(y=e;null!==Ks;){var E=Ks.flags;if(36&E&&vs(y,Ks.alternate,Ks),128&E){w=void 0;var S=Ks.ref;if(null!==S){var _=Ks.stateNode;Ks.tag,w=_,"function"==typeof S?S(w):S.current=w}}Ks=Ks.nextEffect}}catch(C){if(null===Ks)throw Error(i(330));zl(Ks,C),Ks=Ks.nextEffect}}while(null!==Ks);Ks=null,Ba(),Ps=a}else e.current=n;if(Js)Js=!1,el=e,tl=t;else for(Ks=r;null!==Ks;)t=Ks.nextEffect,Ks.nextEffect=null,8&Ks.flags&&((E=Ks).sibling=null,E.stateNode=null),Ks=t;if(0===(r=e.pendingLanes)&&(Xs=null),1===r?e===il?ol++:(ol=0,il=e):ol=0,n=n.stateNode,Sa&&"function"==typeof Sa.onCommitFiberRoot)try{Sa.onCommitFiberRoot(Ea,n,void 0,64==(64&n.current.flags))}catch(C){}if(gl(e,$a()),Ys)throw Ys=!1,e=Qs,Qs=null,e;return 0!=(8&Ps)||Wa(),null}function Il(){for(;null!==Ks;){var e=Ks.alternate;dl||null===ul||(0!=(8&Ks.flags)?et(Ks,ul)&&(dl=!0):13===Ks.tag&&As(e,Ks)&&et(Ks,ul)&&(dl=!0));var t=Ks.flags;0!=(256&t)&&gs(e,Ks),0==(512&t)||Js||(Js=!0,Va(97,(function(){return Dl(),null}))),Ks=Ks.nextEffect}}function Dl(){if(90!==tl){var e=97<tl?97:tl;return tl=90,Za(e,Bl)}return!1}function Ml(e,t){nl.push(t,e),Js||(Js=!0,Va(97,(function(){return Dl(),null})))}function Fl(e,t){rl.push(t,e),Js||(Js=!0,Va(97,(function(){return Dl(),null})))}function Bl(){if(null===el)return!1;var e=el;if(el=null,0!=(48&Ps))throw Error(i(331));var t=Ps;Ps|=32;var n=rl;rl=[];for(var r=0;r<n.length;r+=2){var a=n[r],o=n[r+1],s=a.destroy;if(a.destroy=void 0,"function"==typeof s)try{s()}catch(c){if(null===o)throw Error(i(330));zl(o,c)}}for(n=nl,nl=[],r=0;r<n.length;r+=2){a=n[r],o=n[r+1];try{var l=a.create;a.destroy=l()}catch(c){if(null===o)throw Error(i(330));zl(o,c)}}for(l=e.current.firstEffect;null!==l;)e=l.nextEffect,l.nextEffect=null,8&l.flags&&(l.sibling=null,l.stateNode=null),l=e;return Ps=t,Wa(),!0}function jl(e,t,n){fo(e,t=fs(0,t=cs(n,t),1)),t=fl(),null!==(e=hl(e,1))&&($t(e,1,t),gl(e,t))}function zl(e,t){if(3===e.tag)jl(e,e,t);else for(var n=e.return;null!==n;){if(3===n.tag){jl(n,e,t);break}if(1===n.tag){var r=n.stateNode;if("function"==typeof n.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===Xs||!Xs.has(r))){var a=ps(n,e=cs(t,e),1);if(fo(n,a),a=fl(),null!==(n=hl(n,1)))$t(n,1,a),gl(n,a);else if("function"==typeof r.componentDidCatch&&(null===Xs||!Xs.has(r)))try{r.componentDidCatch(t,e)}catch(o){}break}}n=n.return}}function Ul(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=fl(),e.pingedLanes|=e.suspendedLanes&n,Os===e&&(Ds&n)===n&&(4===Bs||3===Bs&&(62914560&Ds)===Ds&&500>$a()-Gs?Sl(e,0):$s|=n),gl(e,t)}function ql(e,t){var n=e.stateNode;null!==n&&n.delete(t),0===(t=0)&&(0==(2&(t=e.mode))?t=1:0==(4&t)?t=99===Ha()?1:2:(0===ll&&(ll=zs),0===(t=Ut(62914560&~ll))&&(t=4194304))),n=fl(),null!==(e=hl(e,t))&&($t(e,t,n),gl(e,n))}function $l(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function Hl(e,t,n,r){return new $l(e,t,n,r)}function Gl(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Zl(e,t){var n=e.alternate;return null===n?((n=Hl(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.nextEffect=null,n.firstEffect=null,n.lastEffect=null),n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Vl(e,t,n,r,a,o){var s=2;if(r=e,"function"==typeof e)Gl(e)&&(s=1);else if("string"==typeof e)s=5;else e:switch(e){case S:return Wl(n.children,a,o,t);case M:s=8,a|=16;break;case _:s=8,a|=1;break;case C:return(e=Hl(12,n,t,8|a)).elementType=C,e.type=C,e.lanes=o,e;case R:return(e=Hl(13,n,t,a)).type=R,e.elementType=R,e.lanes=o,e;case N:return(e=Hl(19,n,t,a)).elementType=N,e.lanes=o,e;case F:return Kl(n,a,o,t);case B:return(e=Hl(24,n,t,a)).elementType=B,e.lanes=o,e;default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case T:s=10;break e;case A:s=9;break e;case L:s=11;break e;case P:s=14;break e;case O:s=16,r=null;break e;case I:s=22;break e}throw Error(i(130,null==e?e:typeof e,""))}return(t=Hl(s,n,t,a)).elementType=e,t.type=r,t.lanes=o,t}function Wl(e,t,n,r){return(e=Hl(7,e,r,t)).lanes=n,e}function Kl(e,t,n,r){return(e=Hl(23,e,r,t)).elementType=F,e.lanes=n,e}function Yl(e,t,n){return(e=Hl(6,e,null,t)).lanes=n,e}function Ql(e,t,n){return(t=Hl(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Xl(e,t,n){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.pendingContext=this.context=null,this.hydrate=n,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=qt(0),this.expirationTimes=qt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=qt(0),this.mutableSourceEagerHydrationData=null}function Jl(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:E,key:null==r?null:""+r,children:e,containerInfo:t,implementation:n}}function ec(e,t,n,r){var a=t.current,o=fl(),s=pl(a);e:if(n){t:{if(Ye(n=n._reactInternals)!==n||1!==n.tag)throw Error(i(170));var l=n;do{switch(l.tag){case 3:l=l.stateNode.context;break t;case 1:if(va(l.type)){l=l.stateNode.__reactInternalMemoizedMergedChildContext;break t}}l=l.return}while(null!==l);throw Error(i(171))}if(1===n.tag){var c=n.type;if(va(c)){n=wa(n,c,l);break e}}n=l}else n=fa;return null===t.context?t.context=n:t.pendingContext=n,(t=uo(o,s)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),fo(a,t),ml(a,s,o),s}function tc(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function nc(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function rc(e,t){nc(e,t),(e=e.alternate)&&nc(e,t)}function ac(e,t,n){var r=null!=n&&null!=n.hydrationOptions&&n.hydrationOptions.mutableSources||null;if(n=new Xl(e,t,null!=n&&!0===n.hydrate),t=Hl(3,null,null,2===t?7:1===t?3:0),n.current=t,t.stateNode=n,lo(t),e[ea]=n.current,Pr(8===e.nodeType?e.parentNode:e),r)for(e=0;e<r.length;e++){var a=(t=r[e])._getVersion;a=a(t._source),null==n.mutableSourceEagerHydrationData?n.mutableSourceEagerHydrationData=[t,a]:n.mutableSourceEagerHydrationData.push(t,a)}this._internalRoot=n}function oc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function ic(e,t,n,r,a){var o=n._reactRootContainer;if(o){var i=o._internalRoot;if("function"==typeof a){var s=a;a=function(){var e=tc(i);s.call(e)}}ec(t,i,e,a)}else{if(o=n._reactRootContainer=function(e,t){if(t||(t=!(!(t=e?9===e.nodeType?e.documentElement:e.firstChild:null)||1!==t.nodeType||!t.hasAttribute("data-reactroot"))),!t)for(var n;n=e.lastChild;)e.removeChild(n);return new ac(e,0,t?{hydrate:!0}:void 0)}(n,r),i=o._internalRoot,"function"==typeof a){var l=a;a=function(){var e=tc(i);l.call(e)}}xl((function(){ec(t,i,e,a)}))}return tc(i)}function sc(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!oc(t))throw Error(i(200));return Jl(e,t,null,n)}Ws=function(e,t,n){var r=t.lanes;if(null!==e)if(e.memoizedProps!==t.pendingProps||ma.current)Fi=!0;else{if(0==(n&r)){switch(Fi=!1,t.tag){case 3:Vi(t),Wo();break;case 5:Mo(t);break;case 1:va(t.type)&&xa(t);break;case 4:Io(t,t.stateNode.containerInfo);break;case 10:r=t.memoizedProps.value;var a=t.type._context;da(Xa,a._currentValue),a._currentValue=r;break;case 13:if(null!==t.memoizedState)return 0!=(n&t.child.childLanes)?Xi(e,t,n):(da(Bo,1&Bo.current),null!==(t=os(e,t,n))?t.sibling:null);da(Bo,1&Bo.current);break;case 19:if(r=0!=(n&t.childLanes),0!=(64&e.flags)){if(r)return as(e,t,n);t.flags|=64}if(null!==(a=t.memoizedState)&&(a.rendering=null,a.tail=null,a.lastEffect=null),da(Bo,Bo.current),r)break;return null;case 23:case 24:return t.lanes=0,qi(e,t,n)}return os(e,t,n)}Fi=0!=(16384&e.flags)}else Fi=!1;switch(t.lanes=0,t.tag){case 2:if(r=t.type,null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,a=ga(t,pa.current),oo(t,n),a=si(null,t,r,e,a,n),t.flags|=1,"object"==typeof a&&null!==a&&"function"==typeof a.render&&void 0===a.$$typeof){if(t.tag=1,t.memoizedState=null,t.updateQueue=null,va(r)){var o=!0;xa(t)}else o=!1;t.memoizedState=null!==a.state&&void 0!==a.state?a.state:null,lo(t);var s=r.getDerivedStateFromProps;"function"==typeof s&&vo(t,r,s,e),a.updater=bo,t.stateNode=a,a._reactInternals=t,ko(t,r,e,n),t=Zi(null,t,r,!0,o,n)}else t.tag=0,Bi(null,t,a,n),t=t.child;return t;case 16:a=t.elementType;e:{switch(null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),e=t.pendingProps,a=(o=a._init)(a._payload),t.type=a,o=t.tag=function(e){if("function"==typeof e)return Gl(e)?1:0;if(null!=e){if((e=e.$$typeof)===L)return 11;if(e===P)return 14}return 2}(a),e=Qa(a,e),o){case 0:t=Hi(null,t,a,e,n);break e;case 1:t=Gi(null,t,a,e,n);break e;case 11:t=ji(null,t,a,e,n);break e;case 14:t=zi(null,t,a,Qa(a.type,e),r,n);break e}throw Error(i(306,a,""))}return t;case 0:return r=t.type,a=t.pendingProps,Hi(e,t,r,a=t.elementType===r?a:Qa(r,a),n);case 1:return r=t.type,a=t.pendingProps,Gi(e,t,r,a=t.elementType===r?a:Qa(r,a),n);case 3:if(Vi(t),r=t.updateQueue,null===e||null===r)throw Error(i(282));if(r=t.pendingProps,a=null!==(a=t.memoizedState)?a.element:null,co(e,t),mo(t,r,null,n),(r=t.memoizedState.element)===a)Wo(),t=os(e,t,n);else{if((o=(a=t.stateNode).hydrate)&&(Uo=Wr(t.stateNode.containerInfo.firstChild),zo=t,o=qo=!0),o){if(null!=(e=a.mutableSourceEagerHydrationData))for(a=0;a<e.length;a+=2)(o=e[a])._workInProgressVersionPrimary=e[a+1],Ko.push(o);for(n=Ao(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|1024,n=n.sibling}else Bi(e,t,r,n),Wo();t=t.child}return t;case 5:return Mo(t),null===e&&Go(t),r=t.type,a=t.pendingProps,o=null!==e?e.memoizedProps:null,s=a.children,Hr(r,a)?s=null:null!==o&&Hr(r,o)&&(t.flags|=16),$i(e,t),Bi(e,t,s,n),t.child;case 6:return null===e&&Go(t),null;case 13:return Xi(e,t,n);case 4:return Io(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=To(t,null,r,n):Bi(e,t,r,n),t.child;case 11:return r=t.type,a=t.pendingProps,ji(e,t,r,a=t.elementType===r?a:Qa(r,a),n);case 7:return Bi(e,t,t.pendingProps,n),t.child;case 8:case 12:return Bi(e,t,t.pendingProps.children,n),t.child;case 10:e:{r=t.type._context,a=t.pendingProps,s=t.memoizedProps,o=a.value;var l=t.type._context;if(da(Xa,l._currentValue),l._currentValue=o,null!==s)if(l=s.value,0===(o=ur(l,o)?0:0|("function"==typeof r._calculateChangedBits?r._calculateChangedBits(l,o):1073741823))){if(s.children===a.children&&!ma.current){t=os(e,t,n);break e}}else for(null!==(l=t.child)&&(l.return=t);null!==l;){var c=l.dependencies;if(null!==c){s=l.child;for(var u=c.firstContext;null!==u;){if(u.context===r&&0!=(u.observedBits&o)){1===l.tag&&((u=uo(-1,n&-n)).tag=2,fo(l,u)),l.lanes|=n,null!==(u=l.alternate)&&(u.lanes|=n),ao(l.return,n),c.lanes|=n;break}u=u.next}}else s=10===l.tag&&l.type===t.type?null:l.child;if(null!==s)s.return=l;else for(s=l;null!==s;){if(s===t){s=null;break}if(null!==(l=s.sibling)){l.return=s.return,s=l;break}s=s.return}l=s}Bi(e,t,a.children,n),t=t.child}return t;case 9:return a=t.type,r=(o=t.pendingProps).children,oo(t,n),r=r(a=io(a,o.unstable_observedBits)),t.flags|=1,Bi(e,t,r,n),t.child;case 14:return o=Qa(a=t.type,t.pendingProps),zi(e,t,a,o=Qa(a.type,o),r,n);case 15:return Ui(e,t,t.type,t.pendingProps,r,n);case 17:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:Qa(r,a),null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2),t.tag=1,va(r)?(e=!0,xa(t)):e=!1,oo(t,n),wo(t,r,a),ko(t,r,a,n),Zi(null,t,r,!0,e,n);case 19:return as(e,t,n);case 23:case 24:return qi(e,t,n)}throw Error(i(156,t.tag))},ac.prototype.render=function(e){ec(e,this._internalRoot,null,null)},ac.prototype.unmount=function(){var e=this._internalRoot,t=e.containerInfo;ec(null,e,null,(function(){t[ea]=null}))},tt=function(e){13===e.tag&&(ml(e,4,fl()),rc(e,4))},nt=function(e){13===e.tag&&(ml(e,67108864,fl()),rc(e,67108864))},rt=function(e){if(13===e.tag){var t=fl(),n=pl(e);ml(e,n,t),rc(e,n)}},at=function(e,t){return t()},Te=function(e,t,n){switch(t){case"input":if(ne(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var a=oa(r);if(!a)throw Error(i(90));Q(r),ne(r,a)}}}break;case"textarea":ce(e,n);break;case"select":null!=(t=n.value)&&ie(e,!!n.multiple,t,!1)}},Oe=wl,Ie=function(e,t,n,r,a){var o=Ps;Ps|=4;try{return Za(98,e.bind(null,t,n,r,a))}finally{0===(Ps=o)&&(Vs(),Wa())}},De=function(){0==(49&Ps)&&(function(){if(null!==al){var e=al;al=null,e.forEach((function(e){e.expiredLanes|=24&e.pendingLanes,gl(e,$a())}))}Wa()}(),Dl())},Me=function(e,t){var n=Ps;Ps|=2;try{return e(t)}finally{0===(Ps=n)&&(Vs(),Wa())}};var lc={Events:[ra,aa,oa,Ne,Pe,Dl,{current:!1}]},cc={findFiberByHostInstance:na,bundleType:0,version:"17.0.2",rendererPackageName:"react-dom"},uc={bundleType:cc.bundleType,version:cc.version,rendererPackageName:cc.rendererPackageName,rendererConfig:cc.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:x.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Je(e))?null:e.stateNode},findFiberByHostInstance:cc.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var dc=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!dc.isDisabled&&dc.supportsFiber)try{Ea=dc.inject(uc),Sa=dc}catch(ge){}}t.createPortal=sc,t.hydrate=function(e,t,n){if(!oc(t))throw Error(i(200));return ic(null,e,t,!0,n)}},3935:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(4448)},9590:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,a="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function o(e,i){if(e===i)return!0;if(e&&i&&"object"==typeof e&&"object"==typeof i){if(e.constructor!==i.constructor)return!1;var s,l,c,u;if(Array.isArray(e)){if((s=e.length)!=i.length)return!1;for(l=s;0!=l--;)if(!o(e[l],i[l]))return!1;return!0}if(n&&e instanceof Map&&i instanceof Map){if(e.size!==i.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!i.has(l.value[0]))return!1;for(u=e.entries();!(l=u.next()).done;)if(!o(l.value[1],i.get(l.value[0])))return!1;return!0}if(r&&e instanceof Set&&i instanceof Set){if(e.size!==i.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!i.has(l.value[0]))return!1;return!0}if(a&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(i)){if((s=e.length)!=i.length)return!1;for(l=s;0!=l--;)if(e[l]!==i[l])return!1;return!0}if(e.constructor===RegExp)return e.source===i.source&&e.flags===i.flags;if(e.valueOf!==Object.prototype.valueOf)return e.valueOf()===i.valueOf();if(e.toString!==Object.prototype.toString)return e.toString()===i.toString();if((s=(c=Object.keys(e)).length)!==Object.keys(i).length)return!1;for(l=s;0!=l--;)if(!Object.prototype.hasOwnProperty.call(i,c[l]))return!1;if(t&&e instanceof Element)return!1;for(l=s;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!e.$$typeof)&&!o(e[c[l]],i[c[l]]))return!1;return!0}return e!=e&&i!=i}e.exports=function(e,t){try{return o(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},405:(e,t,n)=>{"use strict";n.d(t,{B6:()=>G,ql:()=>J});var r=n(7294),a=n(5697),o=n.n(a),i=n(9590),s=n.n(i),l=n(1143),c=n.n(l),u=n(6774),d=n.n(u);function f(){return f=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},f.apply(this,arguments)}function p(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function h(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(a[n]=e[n]);return a}var g={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},v={rel:["amphtml","canonical","alternate"]},b={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},w=Object.keys(g).map((function(e){return g[e]})),x={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(x).reduce((function(e,t){return e[x[t]]=t,e}),{}),E=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},S=function(e){var t=E(e,g.TITLE),n=E(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var r=E(e,"defaultTitle");return t||r||void 0},_=function(e){return E(e,"onChangeClientState")||function(){}},C=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return f({},e,t)}),{})},T=function(e,t){return t.filter((function(e){return void 0!==e[g.BASE]})).map((function(e){return e[g.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var r=Object.keys(n),a=0;a<r.length;a+=1){var o=r[a].toLowerCase();if(-1!==e.indexOf(o)&&n[o])return t.concat(n)}return t}),[])},A=function(e,t,n){var r={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var a={};n.filter((function(e){for(var n,o=Object.keys(e),i=0;i<o.length;i+=1){var s=o[i],l=s.toLowerCase();-1===t.indexOf(l)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===l&&"stylesheet"===e[l].toLowerCase()||(n=l),-1===t.indexOf(s)||"innerHTML"!==s&&"cssText"!==s&&"itemprop"!==s||(n=s)}if(!n||!e[n])return!1;var c=e[n].toLowerCase();return r[n]||(r[n]={}),a[n]||(a[n]={}),!r[n][c]&&(a[n][c]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var o=Object.keys(a),i=0;i<o.length;i+=1){var s=o[i],l=f({},r[s],a[s]);r[s]=l}return e}),[]).reverse()},L=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},R=function(e){return Array.isArray(e)?e.join(""):e},N=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),r=0;r<n.length;r+=1)if(t[n[r]]&&t[n[r]].includes(e[n[r]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},P=function(e,t){var n;return f({},e,((n={})[t]=void 0,n))},O=[g.NOSCRIPT,g.SCRIPT,g.STYLE],I=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},D=function(e){return Object.keys(e).reduce((function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r}),"")},M=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[x[n]||n]=e[n],t}),t)},F=function(e,t){return t.map((function(t,n){var a,o=((a={key:n})["data-rh"]=!0,a);return Object.keys(t).forEach((function(e){var n=x[e]||e;"innerHTML"===n||"cssText"===n?o.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:o[n]=t[e]})),r.createElement(e,o)}))},B=function(e,t,n){switch(e){case g.TITLE:return{toComponent:function(){return n=t.titleAttributes,(a={key:e=t.title})["data-rh"]=!0,o=M(n,a),[r.createElement(g.TITLE,o,e)];var e,n,a,o},toString:function(){return function(e,t,n,r){var a=D(n),o=R(t);return a?"<"+e+' data-rh="true" '+a+">"+I(o,r)+"</"+e+">":"<"+e+' data-rh="true">'+I(o,r)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return M(t)},toString:function(){return D(t)}};default:return{toComponent:function(){return F(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,r){var a=Object.keys(r).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var a=void 0===r[t]?t:t+'="'+I(r[t],n)+'"';return e?e+" "+a:a}),""),o=r.innerHTML||r.cssText||"",i=-1===O.indexOf(e);return t+"<"+e+' data-rh="true" '+a+(i?"/>":">"+o+"</"+e+">")}),"")}(e,t,n)}}}},j=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,a=e.htmlAttributes,o=e.noscriptTags,i=e.styleTags,s=e.title,l=void 0===s?"":s,c=e.titleAttributes,u=e.linkTags,d=e.metaTags,f=e.scriptTags,p={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,r=e.encode,a=N(e.metaTags,y),o=N(t,v),i=N(n,b);return{priorityMethods:{toComponent:function(){return[].concat(F(g.META,a.priority),F(g.LINK,o.priority),F(g.SCRIPT,i.priority))},toString:function(){return B(g.META,a.priority,r)+" "+B(g.LINK,o.priority,r)+" "+B(g.SCRIPT,i.priority,r)}},metaTags:a.default,linkTags:o.default,scriptTags:i.default}}(e);p=m.priorityMethods,u=m.linkTags,d=m.metaTags,f=m.scriptTags}return{priority:p,base:B(g.BASE,t,r),bodyAttributes:B("bodyAttributes",n,r),htmlAttributes:B("htmlAttributes",a,r),link:B(g.LINK,u,r),meta:B(g.META,d,r),noscript:B(g.NOSCRIPT,o,r),script:B(g.SCRIPT,f,r),style:B(g.STYLE,i,r),title:B(g.TITLE,{title:l,titleAttributes:c},r)}},z=[],U=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?z:n.instances},add:function(e){(n.canUseDOM?z:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?z:n.instances).indexOf(e);(n.canUseDOM?z:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=j({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},q=r.createContext({}),$=o().shape({setHelmet:o().func,helmetInstances:o().shape({get:o().func,add:o().func,remove:o().func})}),H="undefined"!=typeof document,G=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new U(r.props.context,t.canUseDOM),r}return p(t,e),t.prototype.render=function(){return r.createElement(q.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);G.canUseDOM=H,G.propTypes={context:o().shape({helmet:o().shape()}),children:o().node.isRequired},G.defaultProps={context:{}},G.displayName="HelmetProvider";var Z=function(e,t){var n,r=document.head||document.querySelector(g.HEAD),a=r.querySelectorAll(e+"[data-rh]"),o=[].slice.call(a),i=[];return t&&t.length&&t.forEach((function(t){var r=document.createElement(e);for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&("innerHTML"===a?r.innerHTML=t.innerHTML:"cssText"===a?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(a,void 0===t[a]?"":t[a]));r.setAttribute("data-rh","true"),o.some((function(e,t){return n=t,r.isEqualNode(e)}))?o.splice(n,1):i.push(r)})),o.forEach((function(e){return e.parentNode.removeChild(e)})),i.forEach((function(e){return r.appendChild(e)})),{oldTags:o,newTags:i}},V=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),a=r?r.split(","):[],o=[].concat(a),i=Object.keys(t),s=0;s<i.length;s+=1){var l=i[s],c=t[l]||"";n.getAttribute(l)!==c&&n.setAttribute(l,c),-1===a.indexOf(l)&&a.push(l);var u=o.indexOf(l);-1!==u&&o.splice(u,1)}for(var d=o.length-1;d>=0;d-=1)n.removeAttribute(o[d]);a.length===o.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==i.join(",")&&n.setAttribute("data-rh",i.join(","))}},W=function(e,t){var n=e.baseTag,r=e.htmlAttributes,a=e.linkTags,o=e.metaTags,i=e.noscriptTags,s=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,u=e.title,d=e.titleAttributes;V(g.BODY,e.bodyAttributes),V(g.HTML,r),function(e,t){void 0!==e&&document.title!==e&&(document.title=R(e)),V(g.TITLE,t)}(u,d);var f={baseTag:Z(g.BASE,n),linkTags:Z(g.LINK,a),metaTags:Z(g.META,o),noscriptTags:Z(g.NOSCRIPT,i),scriptTags:Z(g.SCRIPT,l),styleTags:Z(g.STYLE,c)},p={},m={};Object.keys(f).forEach((function(e){var t=f[e],n=t.newTags,r=t.oldTags;n.length&&(p[e]=n),r.length&&(m[e]=f[e].oldTags)})),t&&t(),s(e,p,m)},K=null,Y=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).rendered=!1,t}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,r=n.setHelmet,a=null,o=(e=n.helmetInstances.get().map((function(e){var t=f({},e.props);return delete t.context,t})),{baseTag:T(["href"],e),bodyAttributes:C("bodyAttributes",e),defer:E(e,"defer"),encode:E(e,"encodeSpecialCharacters"),htmlAttributes:C("htmlAttributes",e),linkTags:A(g.LINK,["rel","href"],e),metaTags:A(g.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:A(g.NOSCRIPT,["innerHTML"],e),onChangeClientState:_(e),scriptTags:A(g.SCRIPT,["src","innerHTML"],e),styleTags:A(g.STYLE,["cssText"],e),title:S(e),titleAttributes:C("titleAttributes",e),prioritizeSeoTags:L(e,"prioritizeSeoTags")});G.canUseDOM?(t=o,K&&cancelAnimationFrame(K),t.defer?K=requestAnimationFrame((function(){W(t,(function(){K=null}))})):(W(t),K=null)):j&&(a=j(o)),r(a)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(r.Component);Y.propTypes={context:$.isRequired},Y.displayName="HelmetDispatcher";var Q=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}p(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!s()(P(this.props,"helmetData"),P(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case g.SCRIPT:case g.NOSCRIPT:return{innerHTML:t};case g.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return f({},r,((t={})[n.type]=[].concat(r[n.type]||[],[f({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,a=e.newProps,o=e.newChildProps,i=e.nestedChildren;switch(r.type){case g.TITLE:return f({},a,((t={})[r.type]=i,t.titleAttributes=f({},o),t));case g.BODY:return f({},a,{bodyAttributes:f({},o)});case g.HTML:return f({},a,{htmlAttributes:f({},o)});default:return f({},a,((n={})[r.type]=f({},o),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=f({},t);return Object.keys(e).forEach((function(t){var r;n=f({},n,((r={})[t]=e[t],r))})),n},n.warnOnInvalidChildren=function(e,t){return c()(w.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+w.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,a={};return r.Children.forEach(e,(function(e){if(e&&e.props){var r=e.props,o=r.children,i=h(r,Q),s=Object.keys(i).reduce((function(e,t){return e[k[t]||t]=i[t],e}),{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,o),l){case g.FRAGMENT:t=n.mapChildrenToProps(o,t);break;case g.LINK:case g.META:case g.NOSCRIPT:case g.SCRIPT:case g.STYLE:a=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:a,newChildProps:s,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:s,nestedChildren:o})}}})),this.mapArrayTypeChildrenToProps(a,t)},n.render=function(){var e=this.props,t=e.children,n=h(e,X),a=f({},n),o=n.helmetData;return t&&(a=this.mapChildrenToProps(t,a)),!o||o instanceof U||(o=new U(o.context,o.instances)),o?r.createElement(Y,f({},a,{context:o.value,helmetData:void 0})):r.createElement(q.Consumer,null,(function(e){return r.createElement(Y,f({},a,{context:e}))}))},t}(r.Component);J.propTypes={base:o().object,bodyAttributes:o().object,children:o().oneOfType([o().arrayOf(o().node),o().node]),defaultTitle:o().string,defer:o().bool,encodeSpecialCharacters:o().bool,htmlAttributes:o().object,link:o().arrayOf(o().object),meta:o().arrayOf(o().object),noscript:o().arrayOf(o().object),onChangeClientState:o().func,script:o().arrayOf(o().object),style:o().arrayOf(o().object),title:o().string,titleAttributes:o().object,titleTemplate:o().string,prioritizeSeoTags:o().bool,helmetData:o().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},9921:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,a=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,s=n?Symbol.for("react.profiler"):60114,l=n?Symbol.for("react.provider"):60109,c=n?Symbol.for("react.context"):60110,u=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,g=n?Symbol.for("react.lazy"):60116,v=n?Symbol.for("react.block"):60121,b=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function x(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case u:case d:case o:case s:case i:case p:return e;default:switch(e=e&&e.$$typeof){case c:case f:case g:case h:case l:return e;default:return t}}case a:return t}}}function k(e){return x(e)===d}t.AsyncMode=u,t.ConcurrentMode=d,t.ContextConsumer=c,t.ContextProvider=l,t.Element=r,t.ForwardRef=f,t.Fragment=o,t.Lazy=g,t.Memo=h,t.Portal=a,t.Profiler=s,t.StrictMode=i,t.Suspense=p,t.isAsyncMode=function(e){return k(e)||x(e)===u},t.isConcurrentMode=k,t.isContextConsumer=function(e){return x(e)===c},t.isContextProvider=function(e){return x(e)===l},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return x(e)===f},t.isFragment=function(e){return x(e)===o},t.isLazy=function(e){return x(e)===g},t.isMemo=function(e){return x(e)===h},t.isPortal=function(e){return x(e)===a},t.isProfiler=function(e){return x(e)===s},t.isStrictMode=function(e){return x(e)===i},t.isSuspense=function(e){return x(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===d||e===s||e===i||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===h||e.$$typeof===l||e.$$typeof===c||e.$$typeof===f||e.$$typeof===b||e.$$typeof===y||e.$$typeof===w||e.$$typeof===v)},t.typeOf=x},9864:(e,t,n)=>{"use strict";e.exports=n(9921)},8356:(e,t,n)=>{"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function a(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i.apply(this,arguments)}var s=n(7294),l=n(5697),c=[],u=[];function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function f(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(r){var a=d(e[r]);a.loading?t.loading=!0:(t.loaded[r]=a.loaded,t.error=a.error),n.push(a.promise),a.promise.then((function(e){t.loaded[r]=e})).catch((function(e){t.error=e}))}))}catch(r){t.error=r}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function p(e,t){return s.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,f;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=i({loader:null,loading:null,delay:200,timeout:null,render:p,webpack:null,modules:null},t),h=null;function g(){return h||(h=e(m.loader)),h.promise}return c.push(g),"function"==typeof m.webpack&&u.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return g()})),f=d=function(t){function n(n){var r;return o(a(a(r=t.call(this,n)||this)),"retry",(function(){r.setState({error:null,loading:!0,timedOut:!1}),h=e(m.loader),r._loadModule()})),g(),r.state={error:h.error,pastDelay:!1,timedOut:!1,loading:h.loading,loaded:h.loaded},r}r(n,t),n.preload=function(){return g()};var i=n.prototype;return i.UNSAFE_componentWillMount=function(){this._loadModule()},i.componentDidMount=function(){this._mounted=!0},i._loadModule=function(){var e=this;if(this.context.loadable&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.loadable.report(t)})),h.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:h.error,loaded:h.loaded,loading:h.loading}),e._clearTimeouts()};h.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},i.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},i._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},i.render=function(){return this.state.loading||this.state.error?s.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(s.Component),o(d,"contextTypes",{loadable:l.shape({report:l.func.isRequired})}),f}function h(e){return m(d,e)}h.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(f,e)};var g=function(e){function t(){return e.apply(this,arguments)||this}r(t,e);var n=t.prototype;return n.getChildContext=function(){return{loadable:{report:this.props.report}}},n.render=function(){return s.Children.only(this.props.children)},t}(s.Component);function v(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return v(e)}))}o(g,"propTypes",{report:l.func.isRequired}),o(g,"childContextTypes",{loadable:l.shape({report:l.func.isRequired}).isRequired}),h.Capture=g,h.preloadAll=function(){return new Promise((function(e,t){v(c).then(e,t)}))},h.preloadReady=function(){return new Promise((function(e,t){v(u).then(e,e)}))},e.exports=h},8790:(e,t,n)=>{"use strict";n.d(t,{H:()=>s,f:()=>i});var r=n(6775),a=n(7462),o=n(7294);function i(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var a=e.path?(0,r.LX)(t,e):n.length?n[n.length-1].match:r.F0.computeRootMatch(t);return a&&(n.push({route:e,match:a}),e.routes&&i(e.routes,t,n)),a})),n}function s(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?o.createElement(r.rs,n,e.map((function(e,n){return o.createElement(r.AW,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,a.Z)({},n,{},t,{route:e})):o.createElement(e.component,(0,a.Z)({},n,t,{route:e}))}})}))):null}},3727:(e,t,n)=>{"use strict";n.d(t,{OL:()=>y,VK:()=>u,rU:()=>g});var r=n(6775),a=n(5068),o=n(7294),i=n(9318),s=n(7462),l=n(3366),c=n(2177),u=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.lX)(t.props),t}return(0,a.Z)(t,e),t.prototype.render=function(){return o.createElement(r.F0,{history:this.history,children:this.props.children})},t}(o.Component);o.Component;var d=function(e,t){return"function"==typeof e?e(t):e},f=function(e,t){return"string"==typeof e?(0,i.ob)(e,null,null,t):e},p=function(e){return e},m=o.forwardRef;void 0===m&&(m=p);var h=m((function(e,t){var n=e.innerRef,r=e.navigate,a=e.onClick,i=(0,l.Z)(e,["innerRef","navigate","onClick"]),c=i.target,u=(0,s.Z)({},i,{onClick:function(e){try{a&&a(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||c&&"_self"!==c||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),r())}});return u.ref=p!==m&&t||n,o.createElement("a",u)}));var g=m((function(e,t){var n=e.component,a=void 0===n?h:n,u=e.replace,g=e.to,v=e.innerRef,b=(0,l.Z)(e,["component","replace","to","innerRef"]);return o.createElement(r.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=e.history,r=f(d(g,e.location),e.location),l=r?n.createHref(r):"",h=(0,s.Z)({},b,{href:l,navigate:function(){var t=d(g,e.location),r=(0,i.Ep)(e.location)===(0,i.Ep)(f(t));(u||r?n.replace:n.push)(t)}});return p!==m?h.ref=t||v:h.innerRef=v,o.createElement(a,h)}))})),v=function(e){return e},b=o.forwardRef;void 0===b&&(b=v);var y=b((function(e,t){var n=e["aria-current"],a=void 0===n?"page":n,i=e.activeClassName,u=void 0===i?"active":i,p=e.activeStyle,m=e.className,h=e.exact,y=e.isActive,w=e.location,x=e.sensitive,k=e.strict,E=e.style,S=e.to,_=e.innerRef,C=(0,l.Z)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return o.createElement(r.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=w||e.location,i=f(d(S,n),n),l=i.pathname,T=l&&l.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),A=T?(0,r.LX)(n.pathname,{path:T,exact:h,sensitive:x,strict:k}):null,L=!!(y?y(A,n):A),R="function"==typeof m?m(L):m,N="function"==typeof E?E(L):E;L&&(R=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(R,u),N=(0,s.Z)({},N,p));var P=(0,s.Z)({"aria-current":L&&a||null,className:R,style:N,to:i},C);return v!==b?P.ref=t||_:P.innerRef=_,o.createElement(g,P)}))}))},6775:(e,t,n)=>{"use strict";n.d(t,{AW:()=>_,F0:()=>x,rs:()=>N,s6:()=>w,LX:()=>S,k6:()=>O,TH:()=>I});var r=n(5068),a=n(7294),o=n(9318),i=n(5697),s=n.n(i),l=1073741823,c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};function u(e){var t=[];return{on:function(e){t.push(e)},off:function(e){t=t.filter((function(t){return t!==e}))},get:function(){return e},set:function(n,r){e=n,t.forEach((function(t){return t(e,r)}))}}}var d=a.createContext||function(e,t){var n,o,i="__create-react-context-"+function(){var e="__global_unique_id__";return c[e]=(c[e]||0)+1}()+"__",d=function(e){function n(){var t;return(t=e.apply(this,arguments)||this).emitter=u(t.props.value),t}(0,r.Z)(n,e);var a=n.prototype;return a.getChildContext=function(){var e;return(e={})[i]=this.emitter,e},a.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,a=e.value;((o=r)===(i=a)?0!==o||1/o==1/i:o!=o&&i!=i)?n=0:(n="function"==typeof t?t(r,a):l,0!==(n|=0)&&this.emitter.set(e.value,n))}var o,i},a.render=function(){return this.props.children},n}(a.Component);d.childContextTypes=((n={})[i]=s().object.isRequired,n);var f=function(t){function n(){var e;return(e=t.apply(this,arguments)||this).state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}(0,r.Z)(n,t);var a=n.prototype;return a.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?l:t},a.componentDidMount=function(){this.context[i]&&this.context[i].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?l:e},a.componentWillUnmount=function(){this.context[i]&&this.context[i].off(this.onUpdate)},a.getValue=function(){return this.context[i]?this.context[i].get():e},a.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(a.Component);return f.contextTypes=((o={})[i]=s().object,o),{Provider:d,Consumer:f}};const f=d;var p=n(2177),m=n(7462),h=n(9658),g=n.n(h),v=(n(9864),n(3366)),b=(n(8679),function(e){var t=f();return t.displayName=e,t}),y=b("Router-History"),w=b("Router"),x=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,r.Z)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return a.createElement(w.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},a.createElement(y.Provider,{children:this.props.children||null,value:this.props.history}))},t}(a.Component);a.Component;a.Component;var k={},E=0;function S(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,a=n.exact,o=void 0!==a&&a,i=n.strict,s=void 0!==i&&i,l=n.sensitive,c=void 0!==l&&l;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=k[n]||(k[n]={});if(r[e])return r[e];var a=[],o={regexp:g()(e,a,t),keys:a};return E<1e4&&(r[e]=o,E++),o}(n,{end:o,strict:s,sensitive:c}),a=r.regexp,i=r.keys,l=a.exec(e);if(!l)return null;var u=l[0],d=l.slice(1),f=e===u;return o&&!f?null:{path:n,url:"/"===n&&""===u?"/":u,isExact:f,params:i.reduce((function(e,t,n){return e[t.name]=d[n],e}),{})}}),null)}var _=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(w.Consumer,null,(function(t){t||(0,p.Z)(!1);var n=e.props.location||t.location,r=e.props.computedMatch?e.props.computedMatch:e.props.path?S(n.pathname,e.props):t.match,o=(0,m.Z)({},t,{location:n,match:r}),i=e.props,s=i.children,l=i.component,c=i.render;return Array.isArray(s)&&function(e){return 0===a.Children.count(e)}(s)&&(s=null),a.createElement(w.Provider,{value:o},o.match?s?"function"==typeof s?s(o):s:l?a.createElement(l,o):c?c(o):null:"function"==typeof s?s(o):null)}))},t}(a.Component);function C(e){return"/"===e.charAt(0)?e:"/"+e}function T(e,t){if(!e)return t;var n=C(e);return 0!==t.pathname.indexOf(n)?t:(0,m.Z)({},t,{pathname:t.pathname.substr(n.length)})}function A(e){return"string"==typeof e?e:(0,o.Ep)(e)}function L(e){return function(){(0,p.Z)(!1)}}function R(){}a.Component;var N=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(w.Consumer,null,(function(t){t||(0,p.Z)(!1);var n,r,o=e.props.location||t.location;return a.Children.forEach(e.props.children,(function(e){if(null==r&&a.isValidElement(e)){n=e;var i=e.props.path||e.props.from;r=i?S(o.pathname,(0,m.Z)({},e.props,{path:i})):t.match}})),r?a.cloneElement(n,{location:o,computedMatch:r}):null}))},t}(a.Component);var P=a.useContext;function O(){return P(y)}function I(){return P(w).location}},9658:(e,t,n)=>{var r=n(5826);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return s(o(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=f;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,s="",u=t&&t.delimiter||"/";null!=(n=a.exec(e));){var d=n[0],f=n[1],p=n.index;if(s+=e.slice(i,p),i=p+d.length,f)s+=f[1];else{var m=e[i],h=n[2],g=n[3],v=n[4],b=n[5],y=n[6],w=n[7];s&&(r.push(s),s="");var x=null!=h&&null!=m&&m!==h,k="+"===y||"*"===y,E="?"===y||"*"===y,S=n[2]||u,_=v||b;r.push({name:g||o++,prefix:h||"",delimiter:S,optional:E,repeat:k,partial:x,asterisk:!!w,pattern:_?c(_):w?".*":"[^"+l(S)+"]+?"})}}return i<e.length&&(s+=e.substr(i)),s&&r.push(s),r}function i(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function s(e,t){for(var n=new Array(e.length),a=0;a<e.length;a++)"object"==typeof e[a]&&(n[a]=new RegExp("^(?:"+e[a].pattern+")$",d(t)));return function(t,a){for(var o="",s=t||{},l=(a||{}).pretty?i:encodeURIComponent,c=0;c<e.length;c++){var u=e[c];if("string"!=typeof u){var d,f=s[u.name];if(null==f){if(u.optional){u.partial&&(o+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(r(f)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(f)+"`");if(0===f.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var p=0;p<f.length;p++){if(d=l(f[p]),!n[c].test(d))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(d)+"`");o+=(0===p?u.prefix:u.delimiter)+d}}else{if(d=u.asterisk?encodeURI(f).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):l(f),!n[c].test(d))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+d+'"');o+=u.prefix+d}}else o+=u}return o}}function l(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function c(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function u(e,t){return e.keys=t,e}function d(e){return e&&e.sensitive?"":"i"}function f(e,t,n){r(t)||(n=t||n,t=[]);for(var a=(n=n||{}).strict,o=!1!==n.end,i="",s=0;s<e.length;s++){var c=e[s];if("string"==typeof c)i+=l(c);else{var f=l(c.prefix),p="(?:"+c.pattern+")";t.push(c),c.repeat&&(p+="(?:"+f+p+")*"),i+=p=c.optional?c.partial?f+"("+p+")?":"(?:"+f+"("+p+"))?":f+"("+p+")"}}var m=l(n.delimiter||"/"),h=i.slice(-m.length)===m;return a||(i=(h?i.slice(0,-m.length):i)+"(?:"+m+"(?=$))?"),i+=o?"$":a&&h?"":"(?="+m+"|$)",u(new RegExp("^"+i,d(n)),t)}function p(e,t,n){return r(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return u(e,t)}(e,t):r(e)?function(e,t,n){for(var r=[],a=0;a<e.length;a++)r.push(p(e[a],t,n).source);return u(new RegExp("(?:"+r.join("|")+")",d(n)),t)}(e,t,n):function(e,t,n){return f(o(e,n),t,n)}(e,t,n)}},2408:(e,t,n)=>{"use strict";var r=n(7418),a=60103,o=60106;t.Fragment=60107,t.StrictMode=60108,t.Profiler=60114;var i=60109,s=60110,l=60112;t.Suspense=60113;var c=60115,u=60116;if("function"==typeof Symbol&&Symbol.for){var d=Symbol.for;a=d("react.element"),o=d("react.portal"),t.Fragment=d("react.fragment"),t.StrictMode=d("react.strict_mode"),t.Profiler=d("react.profiler"),i=d("react.provider"),s=d("react.context"),l=d("react.forward_ref"),t.Suspense=d("react.suspense"),c=d("react.memo"),u=d("react.lazy")}var f="function"==typeof Symbol&&Symbol.iterator;function p(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h={};function g(e,t,n){this.props=e,this.context=t,this.refs=h,this.updater=n||m}function v(){}function b(e,t,n){this.props=e,this.context=t,this.refs=h,this.updater=n||m}g.prototype.isReactComponent={},g.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(p(85));this.updater.enqueueSetState(this,e,t,"setState")},g.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},v.prototype=g.prototype;var y=b.prototype=new v;y.constructor=b,r(y,g.prototype),y.isPureReactComponent=!0;var w={current:null},x=Object.prototype.hasOwnProperty,k={key:!0,ref:!0,__self:!0,__source:!0};function E(e,t,n){var r,o={},i=null,s=null;if(null!=t)for(r in void 0!==t.ref&&(s=t.ref),void 0!==t.key&&(i=""+t.key),t)x.call(t,r)&&!k.hasOwnProperty(r)&&(o[r]=t[r]);var l=arguments.length-2;if(1===l)o.children=n;else if(1<l){for(var c=Array(l),u=0;u<l;u++)c[u]=arguments[u+2];o.children=c}if(e&&e.defaultProps)for(r in l=e.defaultProps)void 0===o[r]&&(o[r]=l[r]);return{$$typeof:a,type:e,key:i,ref:s,props:o,_owner:w.current}}function S(e){return"object"==typeof e&&null!==e&&e.$$typeof===a}var _=/\/+/g;function C(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function T(e,t,n,r,i){var s=typeof e;"undefined"!==s&&"boolean"!==s||(e=null);var l=!1;if(null===e)l=!0;else switch(s){case"string":case"number":l=!0;break;case"object":switch(e.$$typeof){case a:case o:l=!0}}if(l)return i=i(l=e),e=""===r?"."+C(l,0):r,Array.isArray(i)?(n="",null!=e&&(n=e.replace(_,"$&/")+"/"),T(i,t,n,"",(function(e){return e}))):null!=i&&(S(i)&&(i=function(e,t){return{$$typeof:a,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(i,n+(!i.key||l&&l.key===i.key?"":(""+i.key).replace(_,"$&/")+"/")+e)),t.push(i)),1;if(l=0,r=""===r?".":r+":",Array.isArray(e))for(var c=0;c<e.length;c++){var u=r+C(s=e[c],c);l+=T(s,t,n,u,i)}else if(u=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=f&&e[f]||e["@@iterator"])?e:null}(e),"function"==typeof u)for(e=u.call(e),c=0;!(s=e.next()).done;)l+=T(s=s.value,t,n,u=r+C(s,c++),i);else if("object"===s)throw t=""+e,Error(p(31,"[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t));return l}function A(e,t,n){if(null==e)return e;var r=[],a=0;return T(e,r,"","",(function(e){return t.call(n,e,a++)})),r}function L(e){if(-1===e._status){var t=e._result;t=t(),e._status=0,e._result=t,t.then((function(t){0===e._status&&(t=t.default,e._status=1,e._result=t)}),(function(t){0===e._status&&(e._status=2,e._result=t)}))}if(1===e._status)return e._result;throw e._result}var R={current:null};function N(){var e=R.current;if(null===e)throw Error(p(321));return e}var P={ReactCurrentDispatcher:R,ReactCurrentBatchConfig:{transition:0},ReactCurrentOwner:w,IsSomeRendererActing:{current:!1},assign:r};t.Children={map:A,forEach:function(e,t,n){A(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return A(e,(function(){t++})),t},toArray:function(e){return A(e,(function(e){return e}))||[]},only:function(e){if(!S(e))throw Error(p(143));return e}},t.Component=g,t.PureComponent=b,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=P,t.cloneElement=function(e,t,n){if(null==e)throw Error(p(267,e));var o=r({},e.props),i=e.key,s=e.ref,l=e._owner;if(null!=t){if(void 0!==t.ref&&(s=t.ref,l=w.current),void 0!==t.key&&(i=""+t.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(u in t)x.call(t,u)&&!k.hasOwnProperty(u)&&(o[u]=void 0===t[u]&&void 0!==c?c[u]:t[u])}var u=arguments.length-2;if(1===u)o.children=n;else if(1<u){c=Array(u);for(var d=0;d<u;d++)c[d]=arguments[d+2];o.children=c}return{$$typeof:a,type:e.type,key:i,ref:s,props:o,_owner:l}},t.createContext=function(e,t){return void 0===t&&(t=null),(e={$$typeof:s,_calculateChangedBits:t,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:i,_context:e},e.Consumer=e},t.createElement=E,t.createFactory=function(e){var t=E.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:l,render:e}},t.isValidElement=S,t.lazy=function(e){return{$$typeof:u,_payload:{_status:-1,_result:e},_init:L}},t.memo=function(e,t){return{$$typeof:c,type:e,compare:void 0===t?null:t}},t.useCallback=function(e,t){return N().useCallback(e,t)},t.useContext=function(e,t){return N().useContext(e,t)},t.useDebugValue=function(){},t.useEffect=function(e,t){return N().useEffect(e,t)},t.useImperativeHandle=function(e,t,n){return N().useImperativeHandle(e,t,n)},t.useLayoutEffect=function(e,t){return N().useLayoutEffect(e,t)},t.useMemo=function(e,t){return N().useMemo(e,t)},t.useReducer=function(e,t,n){return N().useReducer(e,t,n)},t.useRef=function(e){return N().useRef(e)},t.useState=function(e){return N().useState(e)},t.version="17.0.2"},7294:(e,t,n)=>{"use strict";e.exports=n(2408)},53:(e,t)=>{"use strict";var n,r,a,o;if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;t.unstable_now=function(){return i.now()}}else{var s=Date,l=s.now();t.unstable_now=function(){return s.now()-l}}if("undefined"==typeof window||"function"!=typeof MessageChannel){var c=null,u=null,d=function(){if(null!==c)try{var e=t.unstable_now();c(!0,e),c=null}catch(n){throw setTimeout(d,0),n}};n=function(e){null!==c?setTimeout(n,0,e):(c=e,setTimeout(d,0))},r=function(e,t){u=setTimeout(e,t)},a=function(){clearTimeout(u)},t.unstable_shouldYield=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var m=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),"function"!=typeof m&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")}var h=!1,g=null,v=-1,b=5,y=0;t.unstable_shouldYield=function(){return t.unstable_now()>=y},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):b=0<e?Math.floor(1e3/e):5};var w=new MessageChannel,x=w.port2;w.port1.onmessage=function(){if(null!==g){var e=t.unstable_now();y=e+b;try{g(!0,e)?x.postMessage(null):(h=!1,g=null)}catch(n){throw x.postMessage(null),n}}else h=!1},n=function(e){g=e,h||(h=!0,x.postMessage(null))},r=function(e,n){v=f((function(){e(t.unstable_now())}),n)},a=function(){p(v),v=-1}}function k(e,t){var n=e.length;e.push(t);e:for(;;){var r=n-1>>>1,a=e[r];if(!(void 0!==a&&0<_(a,t)))break e;e[r]=t,e[n]=a,n=r}}function E(e){return void 0===(e=e[0])?null:e}function S(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,a=e.length;r<a;){var o=2*(r+1)-1,i=e[o],s=o+1,l=e[s];if(void 0!==i&&0>_(i,n))void 0!==l&&0>_(l,i)?(e[r]=l,e[s]=n,r=s):(e[r]=i,e[o]=n,r=o);else{if(!(void 0!==l&&0>_(l,n)))break e;e[r]=l,e[s]=n,r=s}}}return t}return null}function _(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var C=[],T=[],A=1,L=null,R=3,N=!1,P=!1,O=!1;function I(e){for(var t=E(T);null!==t;){if(null===t.callback)S(T);else{if(!(t.startTime<=e))break;S(T),t.sortIndex=t.expirationTime,k(C,t)}t=E(T)}}function D(e){if(O=!1,I(e),!P)if(null!==E(C))P=!0,n(M);else{var t=E(T);null!==t&&r(D,t.startTime-e)}}function M(e,n){P=!1,O&&(O=!1,a()),N=!0;var o=R;try{for(I(n),L=E(C);null!==L&&(!(L.expirationTime>n)||e&&!t.unstable_shouldYield());){var i=L.callback;if("function"==typeof i){L.callback=null,R=L.priorityLevel;var s=i(L.expirationTime<=n);n=t.unstable_now(),"function"==typeof s?L.callback=s:L===E(C)&&S(C),I(n)}else S(C);L=E(C)}if(null!==L)var l=!0;else{var c=E(T);null!==c&&r(D,c.startTime-n),l=!1}return l}finally{L=null,R=o,N=!1}}var F=o;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){P||N||(P=!0,n(M))},t.unstable_getCurrentPriorityLevel=function(){return R},t.unstable_getFirstCallbackNode=function(){return E(C)},t.unstable_next=function(e){switch(R){case 1:case 2:case 3:var t=3;break;default:t=R}var n=R;R=t;try{return e()}finally{R=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=F,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=R;R=e;try{return t()}finally{R=n}},t.unstable_scheduleCallback=function(e,o,i){var s=t.unstable_now();switch("object"==typeof i&&null!==i?i="number"==typeof(i=i.delay)&&0<i?s+i:s:i=s,e){case 1:var l=-1;break;case 2:l=250;break;case 5:l=1073741823;break;case 4:l=1e4;break;default:l=5e3}return e={id:A++,callback:o,priorityLevel:e,startTime:i,expirationTime:l=i+l,sortIndex:-1},i>s?(e.sortIndex=i,k(T,e),null===E(C)&&e===E(T)&&(O?a():O=!0,r(D,i-s))):(e.sortIndex=l,k(C,e),P||N||(P=!0,n(M))),e},t.unstable_wrapCallback=function(e){var t=R;return function(){var n=R;R=t;try{return e.apply(this,arguments)}finally{R=n}}}},3840:(e,t,n)=>{"use strict";e.exports=n(53)},6774:e=>{e.exports=function(e,t,n,r){var a=n?n.call(r,e,t):void 0;if(void 0!==a)return!!a;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),i=Object.keys(t);if(o.length!==i.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),l=0;l<o.length;l++){var c=o[l];if(!s(c))return!1;var u=e[c],d=t[c];if(!1===(a=n?n.call(r,u,d,c):void 0)||void 0===a&&u!==d)return!1}return!0}},2177:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});var r="Invariant failed";function a(e,t){if(!e)throw new Error(r)}},3250:(e,t,n)=>{"use strict";var r=n(7294);var a="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},o=r.useState,i=r.useEffect,s=r.useLayoutEffect,l=r.useDebugValue;function c(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!a(e,n)}catch(r){return!0}}var u="undefined"==typeof window||void 0===window.document||void 0===window.document.createElement?function(e,t){return t()}:function(e,t){var n=t(),r=o({inst:{value:n,getSnapshot:t}}),a=r[0].inst,u=r[1];return s((function(){a.value=n,a.getSnapshot=t,c(a)&&u({inst:a})}),[e,n,t]),i((function(){return c(a)&&u({inst:a}),e((function(){c(a)&&u({inst:a})}))}),[e]),l(n),n};t.useSyncExternalStore=void 0!==r.useSyncExternalStore?r.useSyncExternalStore:u},1688:(e,t,n)=>{"use strict";e.exports=n(3250)},6809:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});const r={title:"Eraser Docs",url:"https://eraser-dev.github.io",baseUrl:"/eraser/docs/",onBrokenLinks:"throw",onBrokenMarkdownLinks:"warn",favicon:"img/favicon.ico",trailingSlash:!1,organizationName:"eraser-dev",projectName:"Eraser",deploymentBranch:"gh-pages",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["classic",{docs:{sidebarPath:"/home/runner/work/eraser/eraser/docs/sidebars.js",routeBasePath:"/"},blog:!1,theme:{customCss:"/home/runner/work/eraser/eraser/docs/src/css/custom.css"},gtag:{trackingID:"G-QV5PNCJ560",anonymizeIP:!0}}]],themeConfig:{navbar:{title:"Eraser",logo:{alt:"Eraser Logo",src:"img/eraser.svg"},items:[{type:"docsVersionDropdown",position:"right",dropdownItemsBefore:[],dropdownItemsAfter:[]},{href:"https://github.com/eraser-dev/eraser",position:"right",className:"header-github-link","aria-label":"GitHub repository"}],hideOnScroll:!1},footer:{style:"dark",copyright:'Copyright \xa9 2024 Linux Foundation. The Linux Foundation\xae (TLF) has registered trademarks and uses trademarks. For a list of TLF trademarks, see <a href="https://www.linuxfoundation.org/trademark-usage/">Trademark Usage</a>.',links:[]},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:[],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},algolia:{appId:"X8MU4GEC0G",apiKey:"aaca7901c07e616a7ec2e1e1f9670809",indexName:"eraser",contextualSearch:!0,searchParameters:{},searchPagePath:"search"},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!0},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},plugins:[],themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],tagline:"",titleDelimiter:"|",noIndex:!1,markdown:{mermaid:!1}}},7462:(e,t,n)=>{"use strict";function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},r.apply(this,arguments)}n.d(t,{Z:()=>r})},5068:(e,t,n)=>{"use strict";function r(e,t){return r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},r(e,t)}function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>a})},3366:(e,t,n)=>{"use strict";function r(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}n.d(t,{Z:()=>r})},7529:e=>{"use strict";e.exports={}},6887:e=>{"use strict";e.exports=JSON.parse('{"/eraser/docs/search-6c2":{"__comp":"1a4e3797","__context":{"plugin":"0a1e161c"}},"/eraser/docs/next-3e9":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"935f2afb"},"/eraser/docs/next-65e":{"__comp":"17896441","content":"a09c2993"},"/eraser/docs/next/architecture-603":{"__comp":"17896441","content":"5281b7a2"},"/eraser/docs/next/code-of-conduct-9c4":{"__comp":"17896441","content":"dea0f9ea"},"/eraser/docs/next/contributing-9d1":{"__comp":"17896441","content":"4d54d076"},"/eraser/docs/next/custom-scanner-ba1":{"__comp":"17896441","content":"5603335d"},"/eraser/docs/next/customization-240":{"__comp":"17896441","content":"fcff9033"},"/eraser/docs/next/exclusion-3b1":{"__comp":"17896441","content":"7b11c903"},"/eraser/docs/next/faq-764":{"__comp":"17896441","content":"0480b142"},"/eraser/docs/next/installation-fd3":{"__comp":"17896441","content":"3b8c55ea"},"/eraser/docs/next/manual-removal-887":{"__comp":"17896441","content":"4fa03c51"},"/eraser/docs/next/metrics-ca7":{"__comp":"17896441","content":"1dba1ecf"},"/eraser/docs/next/quick-start-a1a":{"__comp":"17896441","content":"72e14192"},"/eraser/docs/next/release-management-0b7":{"__comp":"17896441","content":"1b064146"},"/eraser/docs/next/releasing-bf4":{"__comp":"17896441","content":"7d415946"},"/eraser/docs/next/setup-fa3":{"__comp":"17896441","content":"3847b3ea"},"/eraser/docs/next/trivy-26a":{"__comp":"17896441","content":"fd1ae250"},"/eraser/docs/v0.4.x-a77":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"c698fe77"},"/eraser/docs/v0.4.x-7f6":{"__comp":"17896441","content":"22539a87"},"/eraser/docs/v0.4.x/architecture-029":{"__comp":"17896441","content":"24e97898"},"/eraser/docs/v0.4.x/code-of-conduct-7b8":{"__comp":"17896441","content":"c12dc9fd"},"/eraser/docs/v0.4.x/contributing-7d3":{"__comp":"17896441","content":"48ae5635"},"/eraser/docs/v0.4.x/custom-scanner-c20":{"__comp":"17896441","content":"4eac74de"},"/eraser/docs/v0.4.x/customization-431":{"__comp":"17896441","content":"1c30975d"},"/eraser/docs/v0.4.x/exclusion-1fa":{"__comp":"17896441","content":"d40dbec5"},"/eraser/docs/v0.4.x/faq-86f":{"__comp":"17896441","content":"b9421f89"},"/eraser/docs/v0.4.x/installation-559":{"__comp":"17896441","content":"3fcb412e"},"/eraser/docs/v0.4.x/manual-removal-1d0":{"__comp":"17896441","content":"c108e81c"},"/eraser/docs/v0.4.x/quick-start-e66":{"__comp":"17896441","content":"9e350ec0"},"/eraser/docs/v0.4.x/releasing-058":{"__comp":"17896441","content":"2c8b636f"},"/eraser/docs/v0.4.x/setup-223":{"__comp":"17896441","content":"a932041a"},"/eraser/docs/v0.4.x/trivy-604":{"__comp":"17896441","content":"faa9d310"},"/eraser/docs/v0.5.x-574":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"efdb11b6"},"/eraser/docs/v0.5.x-808":{"__comp":"17896441","content":"c66bbf8a"},"/eraser/docs/v0.5.x/architecture-1a5":{"__comp":"17896441","content":"ec0d5d9e"},"/eraser/docs/v0.5.x/code-of-conduct-0e6":{"__comp":"17896441","content":"11d58a17"},"/eraser/docs/v0.5.x/contributing-324":{"__comp":"17896441","content":"0d9a188d"},"/eraser/docs/v0.5.x/custom-scanner-3a5":{"__comp":"17896441","content":"0390b328"},"/eraser/docs/v0.5.x/customization-8f1":{"__comp":"17896441","content":"12682444"},"/eraser/docs/v0.5.x/exclusion-bee":{"__comp":"17896441","content":"fc618254"},"/eraser/docs/v0.5.x/faq-89b":{"__comp":"17896441","content":"fa2b770f"},"/eraser/docs/v0.5.x/installation-a89":{"__comp":"17896441","content":"c73303db"},"/eraser/docs/v0.5.x/manual-removal-e35":{"__comp":"17896441","content":"20cdecc4"},"/eraser/docs/v0.5.x/quick-start-6f3":{"__comp":"17896441","content":"34f2f592"},"/eraser/docs/v0.5.x/releasing-c0e":{"__comp":"17896441","content":"a683e47f"},"/eraser/docs/v0.5.x/setup-df8":{"__comp":"17896441","content":"8eef7690"},"/eraser/docs/v0.5.x/trivy-2b4":{"__comp":"17896441","content":"bf5c5542"},"/eraser/docs/v1.0.x-e8e":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"695a8bbb"},"/eraser/docs/v1.0.x-c03":{"__comp":"17896441","content":"9dbb4f95"},"/eraser/docs/v1.0.x/architecture-0ac":{"__comp":"17896441","content":"bdb5eb86"},"/eraser/docs/v1.0.x/code-of-conduct-ef4":{"__comp":"17896441","content":"dbbf7db4"},"/eraser/docs/v1.0.x/contributing-e7d":{"__comp":"17896441","content":"8cd4fd18"},"/eraser/docs/v1.0.x/custom-scanner-569":{"__comp":"17896441","content":"d7561401"},"/eraser/docs/v1.0.x/customization-85d":{"__comp":"17896441","content":"99ed3086"},"/eraser/docs/v1.0.x/exclusion-3f0":{"__comp":"17896441","content":"62c6dc45"},"/eraser/docs/v1.0.x/faq-8ff":{"__comp":"17896441","content":"4351fb58"},"/eraser/docs/v1.0.x/installation-688":{"__comp":"17896441","content":"72ffabc7"},"/eraser/docs/v1.0.x/manual-removal-8a3":{"__comp":"17896441","content":"8c9fcf50"},"/eraser/docs/v1.0.x/metrics-c54":{"__comp":"17896441","content":"b0fc3de5"},"/eraser/docs/v1.0.x/quick-start-eed":{"__comp":"17896441","content":"9748995c"},"/eraser/docs/v1.0.x/releasing-d7c":{"__comp":"17896441","content":"5af9b662"},"/eraser/docs/v1.0.x/setup-513":{"__comp":"17896441","content":"6ec64a11"},"/eraser/docs/v1.0.x/trivy-5e8":{"__comp":"17896441","content":"6af0c1ea"},"/eraser/docs/v1.1.x-049":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"3e4c86d4"},"/eraser/docs/v1.1.x-f5e":{"__comp":"17896441","content":"c9ca4745"},"/eraser/docs/v1.1.x/architecture-211":{"__comp":"17896441","content":"70b084fe"},"/eraser/docs/v1.1.x/code-of-conduct-78b":{"__comp":"17896441","content":"8f41530a"},"/eraser/docs/v1.1.x/contributing-1ae":{"__comp":"17896441","content":"bffae3e7"},"/eraser/docs/v1.1.x/custom-scanner-762":{"__comp":"17896441","content":"29ca1a0e"},"/eraser/docs/v1.1.x/customization-9ba":{"__comp":"17896441","content":"dc9281b9"},"/eraser/docs/v1.1.x/exclusion-707":{"__comp":"17896441","content":"e36340b6"},"/eraser/docs/v1.1.x/faq-e2c":{"__comp":"17896441","content":"f2ef54d0"},"/eraser/docs/v1.1.x/installation-a45":{"__comp":"17896441","content":"7c6883b5"},"/eraser/docs/v1.1.x/manual-removal-1e9":{"__comp":"17896441","content":"096837f0"},"/eraser/docs/v1.1.x/metrics-f2a":{"__comp":"17896441","content":"2f4673e5"},"/eraser/docs/v1.1.x/quick-start-9b5":{"__comp":"17896441","content":"db59132a"},"/eraser/docs/v1.1.x/releasing-7ee":{"__comp":"17896441","content":"b70ea2cb"},"/eraser/docs/v1.1.x/setup-ea6":{"__comp":"17896441","content":"59e5a646"},"/eraser/docs/v1.1.x/trivy-fd6":{"__comp":"17896441","content":"e1b2cf59"},"/eraser/docs/v1.2.x-813":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"422308df"},"/eraser/docs/v1.2.x-a9e":{"__comp":"17896441","content":"c4f50fcb"},"/eraser/docs/v1.2.x/architecture-45b":{"__comp":"17896441","content":"bbedbacb"},"/eraser/docs/v1.2.x/code-of-conduct-904":{"__comp":"17896441","content":"a708fa78"},"/eraser/docs/v1.2.x/contributing-80d":{"__comp":"17896441","content":"a8f67d08"},"/eraser/docs/v1.2.x/custom-scanner-fd2":{"__comp":"17896441","content":"7196cdd1"},"/eraser/docs/v1.2.x/customization-a26":{"__comp":"17896441","content":"974203ee"},"/eraser/docs/v1.2.x/exclusion-a73":{"__comp":"17896441","content":"07e6d80c"},"/eraser/docs/v1.2.x/faq-c74":{"__comp":"17896441","content":"3a1ed2bb"},"/eraser/docs/v1.2.x/installation-005":{"__comp":"17896441","content":"6739d7ff"},"/eraser/docs/v1.2.x/manual-removal-4e2":{"__comp":"17896441","content":"ed8448fe"},"/eraser/docs/v1.2.x/metrics-c26":{"__comp":"17896441","content":"e3d8f98f"},"/eraser/docs/v1.2.x/quick-start-901":{"__comp":"17896441","content":"101be56a"},"/eraser/docs/v1.2.x/releasing-e74":{"__comp":"17896441","content":"5bc37772"},"/eraser/docs/v1.2.x/setup-62c":{"__comp":"17896441","content":"0fb10398"},"/eraser/docs/v1.2.x/trivy-617":{"__comp":"17896441","content":"b7730d0d"},"/eraser/docs/-e85":{"__comp":"1be78505","__context":{"plugin":"621c6848"},"versionMetadata":"4fb2362d"},"/eraser/docs/-5aa":{"__comp":"17896441","content":"85c70040"},"/eraser/docs/architecture-cf6":{"__comp":"17896441","content":"bc344202"},"/eraser/docs/code-of-conduct-ad2":{"__comp":"17896441","content":"6b8e46b3"},"/eraser/docs/contributing-b07":{"__comp":"17896441","content":"bacc1ae0"},"/eraser/docs/custom-scanner-ffa":{"__comp":"17896441","content":"9ff53b5b"},"/eraser/docs/customization-a79":{"__comp":"17896441","content":"5c838b7d"},"/eraser/docs/exclusion-62c":{"__comp":"17896441","content":"9d55bf96"},"/eraser/docs/faq-630":{"__comp":"17896441","content":"30fb9660"},"/eraser/docs/installation-a40":{"__comp":"17896441","content":"7d6336d8"},"/eraser/docs/manual-removal-734":{"__comp":"17896441","content":"bc8dcae3"},"/eraser/docs/metrics-45e":{"__comp":"17896441","content":"93bf47d2"},"/eraser/docs/quick-start-4ca":{"__comp":"17896441","content":"ae417a11"},"/eraser/docs/release-management-50e":{"__comp":"17896441","content":"e7fdf6d9"},"/eraser/docs/releasing-925":{"__comp":"17896441","content":"b7cd4035"},"/eraser/docs/setup-2c2":{"__comp":"17896441","content":"c853dc39"},"/eraser/docs/trivy-86b":{"__comp":"17896441","content":"44b2adf6"}}')}},e=>{e.O(0,[532],(()=>{return t=7221,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/docs/assets/js/main.424bf04c.js b/docs/assets/js/main.424bf04c.js new file mode 100644 index 0000000000..54072a3126 --- /dev/null +++ b/docs/assets/js/main.424bf04c.js @@ -0,0 +1,2 @@ +/*! For license information please see main.424bf04c.js.LICENSE.txt */ +(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[179],{830:(e,t,n)=>{"use strict";n.d(t,{W:()=>a});var r=n(7294);function a(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});n(7294);var r=n(8356),a=n.n(r),o=n(6887);const i={"0390b328":[()=>n.e(7868).then(n.bind(n,5340)),"@site/versioned_docs/version-v0.5.x/custom-scanner.md",5340],"0480b142":[()=>n.e(836).then(n.bind(n,8976)),"@site/docs/faq.md",8976],"07e6d80c":[()=>n.e(3939).then(n.bind(n,6429)),"@site/versioned_docs/version-v1.2.x/exclusion.md",6429],"096837f0":[()=>n.e(6013).then(n.bind(n,1044)),"@site/versioned_docs/version-v1.1.x/manual-removal.md",1044],"0a1e161c":[()=>n.e(5841).then(n.t.bind(n,7085,19)),"/home/runner/work/eraser/eraser/docs/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",7085],"0d9a188d":[()=>n.e(1865).then(n.bind(n,3582)),"@site/versioned_docs/version-v0.5.x/contributing.md",3582],"0fb10398":[()=>n.e(4781).then(n.bind(n,8457)),"@site/versioned_docs/version-v1.2.x/setup.md",8457],"101be56a":[()=>n.e(7029).then(n.bind(n,7700)),"@site/versioned_docs/version-v1.2.x/quick-start.md",7700],"11d58a17":[()=>n.e(154).then(n.bind(n,9138)),"@site/versioned_docs/version-v0.5.x/code-of-conduct.md",9138],12682444:[()=>n.e(3514).then(n.bind(n,5230)),"@site/versioned_docs/version-v0.5.x/customization.md",5230],17896441:[()=>Promise.all([n.e(532),n.e(7918)]).then(n.bind(n,9413)),"@theme/DocItem",9413],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,6675)),"@theme/SearchPage",6675],"1b064146":[()=>n.e(4178).then(n.bind(n,8368)),"@site/docs/release-management.md",8368],"1c30975d":[()=>n.e(3996).then(n.bind(n,8311)),"@site/versioned_docs/version-v0.4.x/customization.md",8311],"1dba1ecf":[()=>n.e(2510).then(n.bind(n,7937)),"@site/docs/metrics.md",7937],"20cdecc4":[()=>n.e(391).then(n.bind(n,2595)),"@site/versioned_docs/version-v0.5.x/manual-removal.md",2595],"22539a87":[()=>n.e(5964).then(n.bind(n,5174)),"@site/versioned_docs/version-v0.4.x/introduction.md",5174],"24e97898":[()=>n.e(5781).then(n.bind(n,9480)),"@site/versioned_docs/version-v0.4.x/architecture.md",9480],"29ca1a0e":[()=>n.e(5873).then(n.bind(n,8233)),"@site/versioned_docs/version-v1.1.x/custom-scanner.md",8233],"2c8b636f":[()=>n.e(1763).then(n.bind(n,2958)),"@site/versioned_docs/version-v0.4.x/releasing.md",2958],"2f4673e5":[()=>n.e(216).then(n.bind(n,4541)),"@site/versioned_docs/version-v1.1.x/metrics.md",4541],"30fb9660":[()=>n.e(3902).then(n.bind(n,3370)),"@site/versioned_docs/version-v1.3.x/faq.md",3370],"34f2f592":[()=>n.e(9269).then(n.bind(n,5579)),"@site/versioned_docs/version-v0.5.x/quick-start.md",5579],"3847b3ea":[()=>n.e(5581).then(n.bind(n,388)),"@site/docs/setup.md",388],"3a1ed2bb":[()=>n.e(2389).then(n.bind(n,7748)),"@site/versioned_docs/version-v1.2.x/faq.md",7748],"3b8c55ea":[()=>n.e(3217).then(n.bind(n,6995)),"@site/docs/installation.md",6995],"3e4c86d4":[()=>n.e(8180).then(n.t.bind(n,9424,19)),"~docs/default/version-v-1-1-x-metadata-prop-f22.json",9424],"3fcb412e":[()=>n.e(3242).then(n.bind(n,3221)),"@site/versioned_docs/version-v0.4.x/installation.md",3221],"422308df":[()=>n.e(4642).then(n.t.bind(n,1865,19)),"~docs/default/version-v-1-2-x-metadata-prop-53a.json",1865],"4351fb58":[()=>n.e(7551).then(n.bind(n,2435)),"@site/versioned_docs/version-v1.0.x/faq.md",2435],"44b2adf6":[()=>n.e(8841).then(n.bind(n,2947)),"@site/versioned_docs/version-v1.3.x/trivy.md",2947],"48ae5635":[()=>n.e(9212).then(n.bind(n,4397)),"@site/versioned_docs/version-v0.4.x/contributing.md",4397],"4d54d076":[()=>n.e(7080).then(n.bind(n,4651)),"@site/docs/contributing.md",4651],"4eac74de":[()=>n.e(2547).then(n.bind(n,9084)),"@site/versioned_docs/version-v0.4.x/custom-scanner.md",9084],"4fa03c51":[()=>n.e(7395).then(n.bind(n,2447)),"@site/docs/manual-removal.md",2447],"4fb2362d":[()=>n.e(4248).then(n.t.bind(n,6198,19)),"~docs/default/version-v-1-3-x-metadata-prop-1ab.json",6198],"5281b7a2":[()=>n.e(5927).then(n.bind(n,2589)),"@site/docs/architecture.md",2589],"5603335d":[()=>n.e(1031).then(n.bind(n,2058)),"@site/docs/custom-scanner.md",2058],"59e5a646":[()=>n.e(3022).then(n.bind(n,3164)),"@site/versioned_docs/version-v1.1.x/setup.md",3164],"5af9b662":[()=>n.e(5523).then(n.bind(n,7929)),"@site/versioned_docs/version-v1.0.x/releasing.md",7929],"5bc37772":[()=>n.e(8084).then(n.bind(n,601)),"@site/versioned_docs/version-v1.2.x/releasing.md",601],"5c838b7d":[()=>n.e(2242).then(n.bind(n,4394)),"@site/versioned_docs/version-v1.3.x/customization.md",4394],"5e95c892":[()=>n.e(9661).then(n.bind(n,1892)),"@theme/DocsRoot",1892],"621c6848":[()=>n.e(7497).then(n.t.bind(n,3769,19)),"/home/runner/work/eraser/eraser/docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"62c6dc45":[()=>n.e(6252).then(n.bind(n,5979)),"@site/versioned_docs/version-v1.0.x/exclusion.md",5979],"6739d7ff":[()=>n.e(5384).then(n.bind(n,6160)),"@site/versioned_docs/version-v1.2.x/installation.md",6160],"695a8bbb":[()=>n.e(7220).then(n.t.bind(n,9491,19)),"~docs/default/version-v-1-0-x-metadata-prop-19b.json",9491],"6af0c1ea":[()=>n.e(5954).then(n.bind(n,5967)),"@site/versioned_docs/version-v1.0.x/trivy.md",5967],"6b8e46b3":[()=>n.e(7499).then(n.bind(n,5613)),"@site/versioned_docs/version-v1.3.x/code-of-conduct.md",5613],"6ec64a11":[()=>n.e(5255).then(n.bind(n,3682)),"@site/versioned_docs/version-v1.0.x/setup.md",3682],"70b084fe":[()=>n.e(9291).then(n.bind(n,2298)),"@site/versioned_docs/version-v1.1.x/architecture.md",2298],"7196cdd1":[()=>n.e(4404).then(n.bind(n,6311)),"@site/versioned_docs/version-v1.2.x/custom-scanner.md",6311],"72e14192":[()=>n.e(7239).then(n.bind(n,4363)),"@site/docs/quick-start.md",4363],"72ffabc7":[()=>n.e(8301).then(n.bind(n,2274)),"@site/versioned_docs/version-v1.0.x/installation.md",2274],"7b11c903":[()=>n.e(5178).then(n.bind(n,360)),"@site/docs/exclusion.md",360],"7c6883b5":[()=>n.e(783).then(n.bind(n,8650)),"@site/versioned_docs/version-v1.1.x/installation.md",8650],"7d415946":[()=>n.e(6705).then(n.bind(n,2152)),"@site/docs/releasing.md",2152],"7d6336d8":[()=>n.e(3052).then(n.bind(n,5984)),"@site/versioned_docs/version-v1.3.x/installation.md",5984],"85c70040":[()=>n.e(3695).then(n.bind(n,8523)),"@site/versioned_docs/version-v1.3.x/introduction.md",8523],"8c9fcf50":[()=>n.e(4345).then(n.bind(n,6744)),"@site/versioned_docs/version-v1.0.x/manual-removal.md",6744],"8cd4fd18":[()=>n.e(1190).then(n.bind(n,2141)),"@site/versioned_docs/version-v1.0.x/contributing.md",2141],"8eef7690":[()=>n.e(40).then(n.bind(n,7530)),"@site/versioned_docs/version-v0.5.x/setup.md",7530],"8f41530a":[()=>n.e(4292).then(n.bind(n,5093)),"@site/versioned_docs/version-v1.1.x/code-of-conduct.md",5093],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"93bf47d2":[()=>n.e(2288).then(n.bind(n,9177)),"@site/versioned_docs/version-v1.3.x/metrics.md",9177],"974203ee":[()=>n.e(1351).then(n.bind(n,946)),"@site/versioned_docs/version-v1.2.x/customization.md",946],"9748995c":[()=>n.e(8050).then(n.bind(n,9393)),"@site/versioned_docs/version-v1.0.x/quick-start.md",9393],"99ed3086":[()=>n.e(5593).then(n.bind(n,908)),"@site/versioned_docs/version-v1.0.x/customization.md",908],"9d55bf96":[()=>n.e(2238).then(n.bind(n,4681)),"@site/versioned_docs/version-v1.3.x/exclusion.md",4681],"9dbb4f95":[()=>n.e(6842).then(n.bind(n,3553)),"@site/versioned_docs/version-v1.0.x/introduction.md",3553],"9e350ec0":[()=>n.e(7262).then(n.bind(n,9295)),"@site/versioned_docs/version-v0.4.x/quick-start.md",9295],"9ff53b5b":[()=>n.e(9829).then(n.bind(n,8595)),"@site/versioned_docs/version-v1.3.x/custom-scanner.md",8595],a09c2993:[()=>n.e(4128).then(n.bind(n,2214)),"@site/docs/introduction.md",2214],a683e47f:[()=>n.e(846).then(n.bind(n,828)),"@site/versioned_docs/version-v0.5.x/releasing.md",828],a708fa78:[()=>n.e(2356).then(n.bind(n,7109)),"@site/versioned_docs/version-v1.2.x/code-of-conduct.md",7109],a7bd4aaa:[()=>n.e(8518).then(n.bind(n,8564)),"@theme/DocVersionRoot",8564],a8f67d08:[()=>n.e(7591).then(n.bind(n,1228)),"@site/versioned_docs/version-v1.2.x/contributing.md",1228],a932041a:[()=>n.e(5754).then(n.bind(n,3364)),"@site/versioned_docs/version-v0.4.x/setup.md",3364],a94703ab:[()=>Promise.all([n.e(532),n.e(4368)]).then(n.bind(n,2674)),"@theme/DocRoot",2674],ae417a11:[()=>n.e(6300).then(n.bind(n,4590)),"@site/versioned_docs/version-v1.3.x/quick-start.md",4590],b0fc3de5:[()=>n.e(2005).then(n.bind(n,8705)),"@site/versioned_docs/version-v1.0.x/metrics.md",8705],b70ea2cb:[()=>n.e(2534).then(n.bind(n,4076)),"@site/versioned_docs/version-v1.1.x/releasing.md",4076],b7730d0d:[()=>n.e(8976).then(n.bind(n,3453)),"@site/versioned_docs/version-v1.2.x/trivy.md",3453],b7cd4035:[()=>n.e(2229).then(n.bind(n,3496)),"@site/versioned_docs/version-v1.3.x/releasing.md",3496],b9421f89:[()=>n.e(7114).then(n.bind(n,759)),"@site/versioned_docs/version-v0.4.x/faq.md",759],bacc1ae0:[()=>n.e(2579).then(n.bind(n,8282)),"@site/versioned_docs/version-v1.3.x/contributing.md",8282],bbedbacb:[()=>n.e(3523).then(n.bind(n,8819)),"@site/versioned_docs/version-v1.2.x/architecture.md",8819],bc344202:[()=>n.e(6534).then(n.bind(n,4053)),"@site/versioned_docs/version-v1.3.x/architecture.md",4053],bc8dcae3:[()=>n.e(4815).then(n.bind(n,6208)),"@site/versioned_docs/version-v1.3.x/manual-removal.md",6208],bdb5eb86:[()=>n.e(8411).then(n.bind(n,8083)),"@site/versioned_docs/version-v1.0.x/architecture.md",8083],bf5c5542:[()=>n.e(548).then(n.bind(n,5079)),"@site/versioned_docs/version-v0.5.x/trivy.md",5079],bffae3e7:[()=>n.e(7092).then(n.bind(n,4726)),"@site/versioned_docs/version-v1.1.x/contributing.md",4726],c108e81c:[()=>n.e(2156).then(n.bind(n,3817)),"@site/versioned_docs/version-v0.4.x/manual-removal.md",3817],c12dc9fd:[()=>n.e(6325).then(n.bind(n,1294)),"@site/versioned_docs/version-v0.4.x/code-of-conduct.md",1294],c4f50fcb:[()=>n.e(907).then(n.bind(n,5911)),"@site/versioned_docs/version-v1.2.x/introduction.md",5911],c66bbf8a:[()=>n.e(568).then(n.bind(n,4800)),"@site/versioned_docs/version-v0.5.x/introduction.md",4800],c698fe77:[()=>n.e(4993).then(n.t.bind(n,6283,19)),"~docs/default/version-v-0-4-x-metadata-prop-1ae.json",6283],c73303db:[()=>n.e(5082).then(n.bind(n,7328)),"@site/versioned_docs/version-v0.5.x/installation.md",7328],c853dc39:[()=>n.e(7028).then(n.bind(n,9846)),"@site/versioned_docs/version-v1.3.x/setup.md",9846],c9ca4745:[()=>n.e(5243).then(n.bind(n,1379)),"@site/versioned_docs/version-v1.1.x/introduction.md",1379],d40dbec5:[()=>n.e(7677).then(n.bind(n,6026)),"@site/versioned_docs/version-v0.4.x/exclusion.md",6026],d7561401:[()=>n.e(9214).then(n.bind(n,4422)),"@site/versioned_docs/version-v1.0.x/custom-scanner.md",4422],db59132a:[()=>n.e(1619).then(n.bind(n,9070)),"@site/versioned_docs/version-v1.1.x/quick-start.md",9070],dbbf7db4:[()=>n.e(5245).then(n.bind(n,8134)),"@site/versioned_docs/version-v1.0.x/code-of-conduct.md",8134],dc9281b9:[()=>n.e(895).then(n.bind(n,9796)),"@site/versioned_docs/version-v1.1.x/customization.md",9796],dea0f9ea:[()=>n.e(6352).then(n.bind(n,3427)),"@site/docs/code-of-conduct.md",3427],e1b2cf59:[()=>n.e(2023).then(n.bind(n,3748)),"@site/versioned_docs/version-v1.1.x/trivy.md",3748],e36340b6:[()=>n.e(9722).then(n.bind(n,1001)),"@site/versioned_docs/version-v1.1.x/exclusion.md",1001],e3d8f98f:[()=>n.e(6236).then(n.bind(n,9899)),"@site/versioned_docs/version-v1.2.x/metrics.md",9899],e7fdf6d9:[()=>n.e(643).then(n.bind(n,2016)),"@site/versioned_docs/version-v1.3.x/release-management.md",2016],ec0d5d9e:[()=>n.e(1760).then(n.bind(n,5684)),"@site/versioned_docs/version-v0.5.x/architecture.md",5684],ed8448fe:[()=>n.e(1857).then(n.bind(n,859)),"@site/versioned_docs/version-v1.2.x/manual-removal.md",859],efdb11b6:[()=>n.e(4111).then(n.t.bind(n,7064,19)),"~docs/default/version-v-0-5-x-metadata-prop-c47.json",7064],f2ef54d0:[()=>n.e(6039).then(n.bind(n,9081)),"@site/versioned_docs/version-v1.1.x/faq.md",9081],fa2b770f:[()=>n.e(6148).then(n.bind(n,496)),"@site/versioned_docs/version-v0.5.x/faq.md",496],faa9d310:[()=>n.e(6578).then(n.bind(n,2492)),"@site/versioned_docs/version-v0.4.x/trivy.md",2492],fc618254:[()=>n.e(4428).then(n.bind(n,2646)),"@site/versioned_docs/version-v0.5.x/exclusion.md",2646],fcff9033:[()=>n.e(4497).then(n.bind(n,6979)),"@site/docs/customization.md",6979],fd1ae250:[()=>n.e(5221).then(n.bind(n,7105)),"@site/docs/trivy.md",7105]};var s=n(5893);function l(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(9670),u=n(226);function d(e,t){if("*"===e)return a()({loading:l,loader:()=>n.e(1772).then(n.bind(n,1772)),modules:["@theme/NotFound"],webpack:()=>[1772],render(e,t){const n=e.default;return(0,s.jsx)(u.z,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=o[`${e}-${t}`],d={},p=[],f=[],m=(0,c.Z)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),a().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const a=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const o=r.default;if(!o)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof o&&"function"!=typeof o||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{o[e]=r[e]}));let i=a;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=o}));const o=a.__comp;delete a.__comp;const i=a.__context;return delete a.__context,(0,s.jsx)(u.z,{value:i,children:(0,s.jsx)(o,{...a,...n})})}})}const p=[{path:"/eraser/docs/search",component:d("/eraser/docs/search","6c2"),exact:!0},{path:"/eraser/docs/",component:d("/eraser/docs/","8b7"),routes:[{path:"/eraser/docs/next",component:d("/eraser/docs/next","271"),routes:[{path:"/eraser/docs/next",component:d("/eraser/docs/next","ad4"),routes:[{path:"/eraser/docs/next",component:d("/eraser/docs/next","65e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/architecture",component:d("/eraser/docs/next/architecture","603"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/code-of-conduct",component:d("/eraser/docs/next/code-of-conduct","9c4"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/contributing",component:d("/eraser/docs/next/contributing","9d1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/custom-scanner",component:d("/eraser/docs/next/custom-scanner","ba1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/customization",component:d("/eraser/docs/next/customization","240"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/exclusion",component:d("/eraser/docs/next/exclusion","3b1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/faq",component:d("/eraser/docs/next/faq","764"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/installation",component:d("/eraser/docs/next/installation","fd3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/manual-removal",component:d("/eraser/docs/next/manual-removal","887"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/metrics",component:d("/eraser/docs/next/metrics","ca7"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/quick-start",component:d("/eraser/docs/next/quick-start","a1a"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/release-management",component:d("/eraser/docs/next/release-management","0b7"),exact:!0},{path:"/eraser/docs/next/releasing",component:d("/eraser/docs/next/releasing","bf4"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/setup",component:d("/eraser/docs/next/setup","fa3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/next/trivy",component:d("/eraser/docs/next/trivy","26a"),exact:!0,sidebar:"sidebar"}]}]},{path:"/eraser/docs/v0.4.x",component:d("/eraser/docs/v0.4.x","43b"),routes:[{path:"/eraser/docs/v0.4.x",component:d("/eraser/docs/v0.4.x","7d1"),routes:[{path:"/eraser/docs/v0.4.x",component:d("/eraser/docs/v0.4.x","7f6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/architecture",component:d("/eraser/docs/v0.4.x/architecture","029"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/code-of-conduct",component:d("/eraser/docs/v0.4.x/code-of-conduct","7b8"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/contributing",component:d("/eraser/docs/v0.4.x/contributing","7d3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/custom-scanner",component:d("/eraser/docs/v0.4.x/custom-scanner","c20"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/customization",component:d("/eraser/docs/v0.4.x/customization","431"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/exclusion",component:d("/eraser/docs/v0.4.x/exclusion","1fa"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/faq",component:d("/eraser/docs/v0.4.x/faq","86f"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/installation",component:d("/eraser/docs/v0.4.x/installation","559"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/manual-removal",component:d("/eraser/docs/v0.4.x/manual-removal","1d0"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/quick-start",component:d("/eraser/docs/v0.4.x/quick-start","e66"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/releasing",component:d("/eraser/docs/v0.4.x/releasing","058"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/setup",component:d("/eraser/docs/v0.4.x/setup","223"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.4.x/trivy",component:d("/eraser/docs/v0.4.x/trivy","604"),exact:!0,sidebar:"sidebar"}]}]},{path:"/eraser/docs/v0.5.x",component:d("/eraser/docs/v0.5.x","215"),routes:[{path:"/eraser/docs/v0.5.x",component:d("/eraser/docs/v0.5.x","5ca"),routes:[{path:"/eraser/docs/v0.5.x",component:d("/eraser/docs/v0.5.x","808"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/architecture",component:d("/eraser/docs/v0.5.x/architecture","1a5"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/code-of-conduct",component:d("/eraser/docs/v0.5.x/code-of-conduct","0e6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/contributing",component:d("/eraser/docs/v0.5.x/contributing","324"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/custom-scanner",component:d("/eraser/docs/v0.5.x/custom-scanner","3a5"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/customization",component:d("/eraser/docs/v0.5.x/customization","8f1"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/exclusion",component:d("/eraser/docs/v0.5.x/exclusion","bee"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/faq",component:d("/eraser/docs/v0.5.x/faq","89b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/installation",component:d("/eraser/docs/v0.5.x/installation","a89"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/manual-removal",component:d("/eraser/docs/v0.5.x/manual-removal","e35"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/quick-start",component:d("/eraser/docs/v0.5.x/quick-start","6f3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/releasing",component:d("/eraser/docs/v0.5.x/releasing","c0e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/setup",component:d("/eraser/docs/v0.5.x/setup","df8"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v0.5.x/trivy",component:d("/eraser/docs/v0.5.x/trivy","2b4"),exact:!0,sidebar:"sidebar"}]}]},{path:"/eraser/docs/v1.0.x",component:d("/eraser/docs/v1.0.x","2ae"),routes:[{path:"/eraser/docs/v1.0.x",component:d("/eraser/docs/v1.0.x","20b"),routes:[{path:"/eraser/docs/v1.0.x",component:d("/eraser/docs/v1.0.x","c03"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/architecture",component:d("/eraser/docs/v1.0.x/architecture","0ac"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/code-of-conduct",component:d("/eraser/docs/v1.0.x/code-of-conduct","ef4"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/contributing",component:d("/eraser/docs/v1.0.x/contributing","e7d"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/custom-scanner",component:d("/eraser/docs/v1.0.x/custom-scanner","569"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/customization",component:d("/eraser/docs/v1.0.x/customization","85d"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/exclusion",component:d("/eraser/docs/v1.0.x/exclusion","3f0"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/faq",component:d("/eraser/docs/v1.0.x/faq","8ff"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/installation",component:d("/eraser/docs/v1.0.x/installation","688"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/manual-removal",component:d("/eraser/docs/v1.0.x/manual-removal","8a3"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/metrics",component:d("/eraser/docs/v1.0.x/metrics","c54"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/quick-start",component:d("/eraser/docs/v1.0.x/quick-start","eed"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/releasing",component:d("/eraser/docs/v1.0.x/releasing","d7c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/setup",component:d("/eraser/docs/v1.0.x/setup","513"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.0.x/trivy",component:d("/eraser/docs/v1.0.x/trivy","5e8"),exact:!0,sidebar:"sidebar"}]}]},{path:"/eraser/docs/v1.1.x",component:d("/eraser/docs/v1.1.x","35d"),routes:[{path:"/eraser/docs/v1.1.x",component:d("/eraser/docs/v1.1.x","8cd"),routes:[{path:"/eraser/docs/v1.1.x",component:d("/eraser/docs/v1.1.x","f5e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/architecture",component:d("/eraser/docs/v1.1.x/architecture","211"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/code-of-conduct",component:d("/eraser/docs/v1.1.x/code-of-conduct","78b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/contributing",component:d("/eraser/docs/v1.1.x/contributing","1ae"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/custom-scanner",component:d("/eraser/docs/v1.1.x/custom-scanner","762"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/customization",component:d("/eraser/docs/v1.1.x/customization","9ba"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/exclusion",component:d("/eraser/docs/v1.1.x/exclusion","707"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/faq",component:d("/eraser/docs/v1.1.x/faq","e2c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/installation",component:d("/eraser/docs/v1.1.x/installation","a45"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/manual-removal",component:d("/eraser/docs/v1.1.x/manual-removal","1e9"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/metrics",component:d("/eraser/docs/v1.1.x/metrics","f2a"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/quick-start",component:d("/eraser/docs/v1.1.x/quick-start","9b5"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/releasing",component:d("/eraser/docs/v1.1.x/releasing","7ee"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/setup",component:d("/eraser/docs/v1.1.x/setup","ea6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.1.x/trivy",component:d("/eraser/docs/v1.1.x/trivy","fd6"),exact:!0,sidebar:"sidebar"}]}]},{path:"/eraser/docs/v1.2.x",component:d("/eraser/docs/v1.2.x","da9"),routes:[{path:"/eraser/docs/v1.2.x",component:d("/eraser/docs/v1.2.x","e65"),routes:[{path:"/eraser/docs/v1.2.x",component:d("/eraser/docs/v1.2.x","a9e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/architecture",component:d("/eraser/docs/v1.2.x/architecture","45b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/code-of-conduct",component:d("/eraser/docs/v1.2.x/code-of-conduct","904"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/contributing",component:d("/eraser/docs/v1.2.x/contributing","80d"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/custom-scanner",component:d("/eraser/docs/v1.2.x/custom-scanner","fd2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/customization",component:d("/eraser/docs/v1.2.x/customization","a26"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/exclusion",component:d("/eraser/docs/v1.2.x/exclusion","a73"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/faq",component:d("/eraser/docs/v1.2.x/faq","c74"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/installation",component:d("/eraser/docs/v1.2.x/installation","005"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/manual-removal",component:d("/eraser/docs/v1.2.x/manual-removal","4e2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/metrics",component:d("/eraser/docs/v1.2.x/metrics","c26"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/quick-start",component:d("/eraser/docs/v1.2.x/quick-start","901"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/releasing",component:d("/eraser/docs/v1.2.x/releasing","e74"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/setup",component:d("/eraser/docs/v1.2.x/setup","62c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/v1.2.x/trivy",component:d("/eraser/docs/v1.2.x/trivy","617"),exact:!0,sidebar:"sidebar"}]}]},{path:"/eraser/docs/",component:d("/eraser/docs/","334"),routes:[{path:"/eraser/docs/",component:d("/eraser/docs/","16b"),routes:[{path:"/eraser/docs/architecture",component:d("/eraser/docs/architecture","cf6"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/code-of-conduct",component:d("/eraser/docs/code-of-conduct","ad2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/contributing",component:d("/eraser/docs/contributing","b07"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/custom-scanner",component:d("/eraser/docs/custom-scanner","ffa"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/customization",component:d("/eraser/docs/customization","a79"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/exclusion",component:d("/eraser/docs/exclusion","62c"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/faq",component:d("/eraser/docs/faq","630"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/installation",component:d("/eraser/docs/installation","a40"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/manual-removal",component:d("/eraser/docs/manual-removal","734"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/metrics",component:d("/eraser/docs/metrics","45e"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/quick-start",component:d("/eraser/docs/quick-start","4ca"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/release-management",component:d("/eraser/docs/release-management","50e"),exact:!0},{path:"/eraser/docs/releasing",component:d("/eraser/docs/releasing","925"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/setup",component:d("/eraser/docs/setup","2c2"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/trivy",component:d("/eraser/docs/trivy","86b"),exact:!0,sidebar:"sidebar"},{path:"/eraser/docs/",component:d("/eraser/docs/","5aa"),exact:!0,sidebar:"sidebar"}]}]}]},{path:"*",component:d("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,t:()=>i});var r=n(7294),a=n(5893);const o=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,a.jsx)(o.Provider,{value:n,children:t})}},7221:(e,t,n)=>{"use strict";var r=n(7294),a=n(745),o=n(3727),i=n(405),s=n(412);const l=[n(6657),n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790),p=n(5893);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var m=n(5742),h=n(2263),g=n(4996),b=n(6668),v=n(833),y=n(4711),x=n(9727),w=n(3320),k=n(8780),S=n(197);function _(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.Z)(),r=(0,y.l)(),a=n[e].htmlLang,o=e=>e.replace("-","_");return(0,p.jsxs)(m.Z,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:o(a)}),Object.values(n).filter((e=>a!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:o(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.Z)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.Z)(),{pathname:r}=(0,u.TH)();return e+(0,k.applyTrailingSlash)((0,g.Z)(r),{trailingSlash:n,baseUrl:t})}(),a=t?`${n}${t}`:r;return(0,p.jsxs)(m.Z,{children:[(0,p.jsx)("meta",{property:"og:url",content:a}),(0,p.jsx)("link",{rel:"canonical",href:a})]})}function C(){const{i18n:{currentLocale:e}}=(0,h.Z)(),{metadata:t,image:n}=(0,b.L)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(m.Z,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:x.h})]}),n&&(0,p.jsx)(v.d,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(_,{}),(0,p.jsx)(S.Z,{tag:w.HX,locale:e}),(0,p.jsx)(m.Z,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const T=new Map;function j(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var A=n(8934),L=n(8940),R=n(469);function N(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];const a=l.map((t=>{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>a.forEach((e=>e?.()))}const P=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,R.Z)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),N("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class I extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?N("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=N("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(P,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.AW,{location:t,render:()=>e})})}}const D=I,M="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner",z="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${M}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n<div id="${F}" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">${e}</span> ${"/"===e?" (default value)":""}</p>\n <p>We suggest trying baseUrl = <span id="${z}" style="font-weight: bold; color: green;"></span></p>\n</div>\n`}(e)).replace(/</g,"\\<")};\n bannerContainer.innerHTML = bannerHtml;\n document.body.prepend(bannerContainer);\n var suggestionContainer = document.getElementById('${z}');\n var actualHomePagePath = window.location.pathname;\n var suggestedBaseUrl = actualHomePagePath.substr(-1) === '/'\n ? actualHomePagePath\n : actualHomePagePath + '/';\n suggestionContainer.innerHTML = suggestedBaseUrl;\n}\n`}function $(){const{siteConfig:{baseUrl:e}}=(0,h.Z)();return(0,p.jsx)(p.Fragment,{children:!s.Z.canUseDOM&&(0,p.jsx)(m.Z,{children:(0,p.jsx)("script",{children:B(e)})})})}function U(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,h.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?(0,p.jsx)($,{}):null}function q(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:r,localeConfigs:a}}=(0,h.Z)(),o=(0,g.Z)(e),{htmlLang:i,direction:s}=a[r];return(0,p.jsxs)(m.Z,{children:[(0,p.jsx)("html",{lang:i,dir:s}),(0,p.jsx)("title",{children:t}),(0,p.jsx)("meta",{property:"og:title",content:t}),(0,p.jsx)("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&(0,p.jsx)("meta",{name:"robots",content:"noindex, nofollow"}),e&&(0,p.jsx)("link",{rel:"icon",href:o})]})}var H=n(4763),Z=n(2389);function G(){const e=(0,Z.Z)();return(0,p.jsx)(m.Z,{children:(0,p.jsx)("html",{"data-has-hydrated":e})})}function V(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return(0,p.jsx)(H.Z,{children:(0,p.jsx)(L.M,{children:(0,p.jsxs)(A.t,{children:[(0,p.jsxs)(f,{children:[(0,p.jsx)(q,{}),(0,p.jsx)(C,{}),(0,p.jsx)(U,{}),(0,p.jsx)(D,{location:j(t),children:e})]}),(0,p.jsx)(G,{})]})})})}var W=n(6887);const Q=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const a=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;a?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var K=n(9670);const Y=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!J()&&!X.has(e)&&!Y.has(e))(e))return!1;Y.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(W).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,K.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Q(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),O(e))},te=Object.freeze(ee),ne=Boolean(!0);if(s.Z.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(i.B6,{children:(0,p.jsx)(o.VK,{children:(0,p.jsx)(V,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(ne)r.startTransition((()=>{a.hydrateRoot(e,t,{onRecoverableError:n})}));else{const o=a.createRoot(e,{onRecoverableError:n});r.startTransition((()=>{o.render(t)}))}};O(window.location.pathname).then(s)}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>d,M:()=>p});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-QV5PNCJ560"],"anonymizeIP":true,"id":"default"}},"docusaurus-plugin-content-docs":{"default":{"path":"/eraser/docs/","versions":[{"name":"current","label":"Next","isLast":false,"path":"/eraser/docs/next","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/next/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/next/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/next/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/next/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/next/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/next/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/next/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/next/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/next/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/next/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/next/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/next/quick-start","sidebar":"sidebar"},{"id":"release-management","path":"/eraser/docs/next/release-management"},{"id":"releasing","path":"/eraser/docs/next/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/next/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/next/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/next/","label":"introduction"}}}},{"name":"v1.3.x","label":"v1.3.x","isLast":true,"path":"/eraser/docs/","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/quick-start","sidebar":"sidebar"},{"id":"release-management","path":"/eraser/docs/release-management"},{"id":"releasing","path":"/eraser/docs/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/","label":"introduction"}}}},{"name":"v1.2.x","label":"v1.2.x","isLast":false,"path":"/eraser/docs/v1.2.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v1.2.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v1.2.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v1.2.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v1.2.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v1.2.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v1.2.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v1.2.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v1.2.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v1.2.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v1.2.x/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/v1.2.x/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v1.2.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v1.2.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v1.2.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v1.2.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v1.2.x/","label":"introduction"}}}},{"name":"v1.1.x","label":"v1.1.x","isLast":false,"path":"/eraser/docs/v1.1.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v1.1.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v1.1.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v1.1.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v1.1.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v1.1.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v1.1.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v1.1.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v1.1.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v1.1.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v1.1.x/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/v1.1.x/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v1.1.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v1.1.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v1.1.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v1.1.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v1.1.x/","label":"introduction"}}}},{"name":"v1.0.x","label":"v1.0.x","isLast":false,"path":"/eraser/docs/v1.0.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v1.0.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v1.0.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v1.0.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v1.0.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v1.0.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v1.0.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v1.0.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v1.0.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v1.0.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v1.0.x/manual-removal","sidebar":"sidebar"},{"id":"metrics","path":"/eraser/docs/v1.0.x/metrics","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v1.0.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v1.0.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v1.0.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v1.0.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v1.0.x/","label":"introduction"}}}},{"name":"v0.5.x","label":"v0.5.x","isLast":false,"path":"/eraser/docs/v0.5.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v0.5.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v0.5.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v0.5.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v0.5.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v0.5.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v0.5.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v0.5.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v0.5.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v0.5.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v0.5.x/manual-removal","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v0.5.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v0.5.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v0.5.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v0.5.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v0.5.x/","label":"introduction"}}}},{"name":"v0.4.x","label":"v0.4.x","isLast":false,"path":"/eraser/docs/v0.4.x","mainDocId":"introduction","docs":[{"id":"architecture","path":"/eraser/docs/v0.4.x/architecture","sidebar":"sidebar"},{"id":"code-of-conduct","path":"/eraser/docs/v0.4.x/code-of-conduct","sidebar":"sidebar"},{"id":"contributing","path":"/eraser/docs/v0.4.x/contributing","sidebar":"sidebar"},{"id":"custom-scanner","path":"/eraser/docs/v0.4.x/custom-scanner","sidebar":"sidebar"},{"id":"customization","path":"/eraser/docs/v0.4.x/customization","sidebar":"sidebar"},{"id":"exclusion","path":"/eraser/docs/v0.4.x/exclusion","sidebar":"sidebar"},{"id":"faq","path":"/eraser/docs/v0.4.x/faq","sidebar":"sidebar"},{"id":"installation","path":"/eraser/docs/v0.4.x/installation","sidebar":"sidebar"},{"id":"introduction","path":"/eraser/docs/v0.4.x/","sidebar":"sidebar"},{"id":"manual-removal","path":"/eraser/docs/v0.4.x/manual-removal","sidebar":"sidebar"},{"id":"quick-start","path":"/eraser/docs/v0.4.x/quick-start","sidebar":"sidebar"},{"id":"releasing","path":"/eraser/docs/v0.4.x/releasing","sidebar":"sidebar"},{"id":"setup","path":"/eraser/docs/v0.4.x/setup","sidebar":"sidebar"},{"id":"trivy","path":"/eraser/docs/v0.4.x/trivy","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/eraser/docs/v0.4.x/","label":"introduction"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(7529);const l=JSON.parse('{"docusaurusVersion":"3.1.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.1.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.1.0"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.1.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.1.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.1.0"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.1.0"}}}');var c=n(5893);const u={siteConfig:a.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(412),o=n(5742),i=n(8780),s=n(7372),l=n(5893);function c(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function d(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)(f,{fallback:()=>(0,l.jsx)(c,{error:t,tryAgain:n}),children:[(0,l.jsx)(o.Z,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(s.Z,{children:(0,l.jsx)(c,{error:t,tryAgain:n})})]})}const p=e=>(0,l.jsx)(d,{...e});class f extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??p)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(7294);var r=n(405),a=n(5893);function o(e){return(0,a.jsx)(r.ql,{...e})}},3692:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(3727),o=n(8780),i=n(2263),s=n(3919),l=n(412),c=n(8138),u=n(4996),d=n(5893);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:h,"data-noBrokenLinkCheck":g,autoAddBaseUrl:b=!0,...v}=e;const{siteConfig:{trailingSlash:y,baseUrl:x}}=(0,i.Z)(),{withBaseUrl:w}=(0,u.C)(),k=(0,c.Z)(),S=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>S.current));const _=p||f;const E=(0,s.Z)(_),C=_?.replace("pathname://","");let T=void 0!==C?(j=C,b&&(e=>e.startsWith("/"))(j)?w(j):j):void 0;var j;T&&E&&(T=(0,o.applyTrailingSlash)(T,{trailingSlash:y,baseUrl:x}));const A=(0,r.useRef)(!1),L=n?a.OL:a.rU,R=l.Z.canUseIntersectionObserver,N=(0,r.useRef)(),P=()=>{A.current||null==T||(window.docusaurus.preload(T),A.current=!0)};(0,r.useEffect)((()=>(!R&&E&&null!=T&&window.docusaurus.prefetch(T),()=>{R&&N.current&&N.current.disconnect()})),[N,T,R,E]);const O=T?.startsWith("#")??!1,I=!T||!E||O;return I||g||k.collectLink(T),I?(0,d.jsx)("a",{ref:S,href:T,..._&&!E&&{target:"_blank",rel:"noopener noreferrer"},...v}):(0,d.jsx)(L,{...v,onMouseEnter:P,onTouchStart:P,innerRef:e=>{S.current=e,R&&e&&E&&(N.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(N.current.unobserve(e),N.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),N.current.observe(e))},to:T,...n&&{isActive:h,activeClassName:m}})}const f=r.forwardRef(p)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c,I:()=>l});var r=n(7294),a=n(5893);function o(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(7529);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return o(s({message:n,id:r}),t)}function c(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal <Translate> children",t),new Error("The Docusaurus <Translate> component only accept simple string values");const i=s({message:t,id:n});return(0,a.jsx)(a.Fragment,{children:o(i,r)})}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var r=n(7294),a=n(2263),o=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,a.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:a=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(a)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},8138:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(7294);n(5893);const a=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),o=()=>(0,r.useContext)(a);function i(){return o()}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},469:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function a(e){const t={};return function e(n,a){Object.entries(n).forEach((n=>{let[o,i]=n;const s=a?`${a}.${o}`:o;r(i)?e(i,s):t[s]=i}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>o,z:()=>i});var r=n(7294),a=n(5893);const o=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(o),s=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,a.jsx)(o.Provider,{value:s,children:t})}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>b,gA:()=>f,WS:()=>m,_r:()=>d,Jo:()=>v,zh:()=>p,yW:()=>g,gB:()=>h});var r=n(6550),a=n(2263),o=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,a.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}function c(e,t){const n=l(e,t),a=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,p=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const r=i(e),a=r?.[t];if(!a&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return a}("docusaurus-plugin-content-docs",e,{failfast:!0});function f(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function m(e){void 0===e&&(e={});const t=f(e),{pathname:n}=(0,r.TH)();if(!t)return;return{activePlugin:t,activeVersion:l(t.pluginData,n)}}function h(e){return p(e).versions}function g(e){const t=p(e);return s(t)}function b(e){const t=p(e),{pathname:n}=(0,r.TH)();return c(t,n)}function v(e){const t=p(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:c(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},6657:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(2573),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(6854),n(6726)(`./prism-${e}`)})),delete globalThis.Prism}(r.p1)},2503:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});n(7294);var r=n(512),a=n(5999),o=n(6668),i=n(3692),s=n(8138);const l={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var c=n(5893);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.Z)(),{navbar:{hideOnScroll:p}}=(0,o.L)();if("h1"===t||!n)return(0,c.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,a.I)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,c.jsxs)(t,{...u,className:(0,r.Z)("anchor",p?l.anchorWithHideOnScrollNavbar:l.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,c.jsx)(i.Z,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(7294);const r={iconExternalLink:"iconExternalLink_nPIU"};var a=n(5893);function o(e){let{width:t=13.5,height:n=13.5}=e;return(0,a.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,a.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},7372:(e,t,n)=>{"use strict";n.d(t,{Z:()=>Nt});var r=n(7294),a=n(512),o=n(4763),i=n(833),s=n(6550),l=n(5999),c=n(5936),u=n(5893);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,l.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??m,{containerRef:n,onClick:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var g=n(5281),b=n(9727);const v={skipToContent:"skipToContent_fXgn"};function y(){return(0,u.jsx)(h,{className:v.skipToContent})}var x=n(6668),w=n(9689);function k(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:a=1.2,className:o,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:a,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const S={closeButton:"closeButton_CVFx"};function _(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,l.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,a.Z)("clean-btn close",S.closeButton,e.className),children:(0,u.jsx)(k,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,x.L)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,a.Z)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function j(){const{announcementBar:e}=(0,x.L)(),{isActive:t,close:n}=(0,w.nT)();if(!t)return null;const{backgroundColor:r,textColor:a,isCloseable:o}=e;return(0,u.jsxs)("div",{className:T.announcementBar,style:{backgroundColor:r,color:a},role:"banner",children:[o&&(0,u.jsx)("div",{className:T.announcementBarPlaceholder}),(0,u.jsx)(C,{className:T.announcementBarContent}),o&&(0,u.jsx)(_,{onClick:n,className:T.announcementBarClose})]})}var A=n(3163),L=n(2466);var R=n(902),N=n(3102);const P=r.createContext(null);function O(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,N.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,R.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return(0,u.jsx)(P.Provider,{value:n,children:t})}function I(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function D(){const e=(0,r.useContext)(P);if(!e)throw new R.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,N.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:I(o)})),[a,o,t])}function M(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:o}=D();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":o}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var F=n(2949),z=n(2389);function B(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function q(e){let{className:t,buttonClassName:n,value:r,onChange:o}=e;const i=(0,z.Z)(),s=(0,l.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,l.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,a.Z)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,a.Z)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>o("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(B,{className:(0,a.Z)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)($,{className:(0,a.Z)(U.toggleIcon,U.darkToggleIcon)})]})})}const H=r.memo(q),Z={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function G(e){let{className:t}=e;const n=(0,x.L)().navbar.style,r=(0,x.L)().colorMode.disableSwitch,{colorMode:a,setColorMode:o}=(0,F.I)();return r?null:(0,u.jsx)(H,{className:t,buttonClassName:"dark"===n?Z.darkNavbarColorModeToggle:void 0,value:a,onChange:o})}var V=n(1327);function W(){return(0,u.jsx)(V.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,A.e)();return(0,u.jsx)("button",{type:"button","aria-label":(0,l.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(k,{color:"var(--ifm-color-emphasis-600)"})})}function K(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(W,{}),(0,u.jsx)(G,{className:"margin-right--md"}),(0,u.jsx)(Q,{})]})}var Y=n(3692),X=n(4996),J=n(3919),ee=n(8022),te=n(9471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:a,label:o,html:i,isDropdownLink:s,prependBaseUrlToHref:l,...c}=e;const d=(0,X.Z)(r),p=(0,X.Z)(t),f=(0,X.Z)(a,{forcePrependBaseUrl:!0}),m=o&&a&&!(0,J.Z)(a),h=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[o,m&&(0,u.jsx)(te.Z,{...s&&{width:12,height:12}})]})};return a?(0,u.jsx)(Y.Z,{href:l?f:a,...c,...h}):(0,u.jsx)(Y.Z,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee.F)(n,t.pathname):t.pathname.startsWith(p)},...c,...h})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const o=(0,u.jsx)(ne,{className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:o}):o}function ae(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,a.Z)("menu__link",t),...r})})}function oe(e){let{mobile:t=!1,position:n,...r}=e;const a=t?ae:re;return(0,u.jsx)(a,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(6043),se=n(8596),le=n(2263);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.Mg)(e.to,t)||!!(0,ee.F)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:o,onClick:i,...s}=e;const l=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{l.current&&!l.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,a.Z)("navbar__link",o),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(He,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:o,onClick:i,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,s.TH)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[c,d,m]),(0,u.jsxs)("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,a.Z)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,u.jsx)(ie.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(He,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var me=n(4711);function he(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const ge="iconLanguage_nlXk";var be=n(3935);function ve(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var ye=n(830),xe=["translations"];function we(){return we=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},we.apply(this,arguments)}function ke(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null==n)return;var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(l){s=!0,a=l}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return Se(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Se(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Se(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function _e(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var Ee="Ctrl";var Ce=r.forwardRef((function(e,t){var n=e.translations,a=void 0===n?{}:n,o=_e(e,xe),i=a.buttonText,s=void 0===i?"Search":i,l=a.buttonAriaLabel,c=void 0===l?"Search":l,u=ke((0,r.useState)(null),2),d=u[0],p=u[1];return(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?p("\u2318"):p(Ee))}),[]),r.createElement("button",we({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(ye.W,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&r.createElement(r.Fragment,null,r.createElement("kbd",{className:"DocSearch-Button-Key"},d===Ee?r.createElement(ve,null):d),r.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Te=n(5742),je=n(6177),Ae=n(239),Le=n(3320);const Re={button:{buttonText:(0,l.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,l.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,l.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,l.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,l.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,l.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,l.I)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,l.I)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,l.I)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,l.I)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,l.I)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,l.I)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,l.I)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,l.I)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,l.I)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,l.I)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,l.I)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,l.I)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,l.I)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,l.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,l.I)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Ne=null;function Pe(e){let{hit:t,children:n}=e;return(0,u.jsx)(Y.Z,{to:t.url,children:n})}function Oe(e){let{state:t,onClose:n}=e;const r=(0,je.M)();return(0,u.jsx)(Y.Z,{to:r(t.query),onClick:n,children:(0,u.jsx)(l.Z,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Ie(e){let{contextualSearch:t,externalUrlRegex:a,...o}=e;const{siteMetadata:i}=(0,le.Z)(),l=(0,Ae.l)(),c=function(){const{locale:e,tags:t}=(0,Le._q)();return[`language:${e}`,t.map((e=>`docusaurus_tag:${e}`))]}(),d=o.searchParameters?.facetFilters??[],p=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(c,d):d,f={...o.searchParameters,facetFilters:p},m=(0,s.k6)(),h=(0,r.useRef)(null),g=(0,r.useRef)(null),[b,v]=(0,r.useState)(!1),[y,x]=(0,r.useState)(void 0),w=(0,r.useCallback)((()=>Ne?Promise.resolve():Promise.all([n.e(1426).then(n.bind(n,1426)),Promise.all([n.e(532),n.e(6945)]).then(n.bind(n,6945)),Promise.all([n.e(532),n.e(8894)]).then(n.bind(n,8894))]).then((e=>{let[{DocSearchModal:t}]=e;Ne=t}))),[]),k=(0,r.useCallback)((()=>{w().then((()=>{h.current=document.createElement("div"),document.body.insertBefore(h.current,document.body.firstChild),v(!0)}))}),[w,v]),S=(0,r.useCallback)((()=>{v(!1),h.current?.remove()}),[v]),_=(0,r.useCallback)((e=>{w().then((()=>{v(!0),x(e.key)}))}),[w,v,x]),E=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee.F)(a,t)?window.location.href=t:m.push(t)}}).current,C=(0,r.useRef)((e=>o.transformItems?o.transformItems(e):e.map((e=>({...e,url:l(e.url)}))))).current,T=(0,r.useMemo)((()=>e=>(0,u.jsx)(Oe,{...e,onClose:S})),[S]),j=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,a=e.onClose,o=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){var r;(27===e.keyCode&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?a():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&o&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&o(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,a,o,i])}({isOpen:b,onOpen:k,onClose:S,onInput:_,searchButtonRef:g}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Te.Z,{children:(0,u.jsx)("link",{rel:"preconnect",href:`https://${o.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})}),(0,u.jsx)(Ce,{onTouchStart:w,onFocus:w,onMouseOver:w,onClick:k,ref:g,translations:Re.button}),b&&Ne&&h.current&&(0,be.createPortal)((0,u.jsx)(Ne,{onClose:S,initialScrollY:window.scrollY,initialQuery:y,navigator:E,transformItems:C,hitComponent:Pe,transformSearchClient:j,...o.searchPagePath&&{resultsFooterComponent:T},...o,searchParameters:f,placeholder:Re.placeholder,translations:Re.modal}),h.current)]})}function De(){const{siteConfig:e}=(0,le.Z)();return(0,u.jsx)(Ie,{...e.themeConfig.algolia})}const Me={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Fe(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,a.Z)(n,Me.navbarSearchContainer),children:t})}var ze=n(143),Be=n(2802);var $e=n(373);const Ue=e=>e.docs.find((t=>t.id===e.mainDocId));const qe={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:a="",...o}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.Z)(),p=(0,me.l)(),{search:f,hash:m}=(0,s.TH)(),h=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}${a}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],g=t?(0,l.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...o,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(he,{className:ge}),g]}),items:h})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Fe,{className:n,children:(0,u.jsx)(De,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:o=!1}=e;const i=o?"li":"div";return(0,u.jsx)(i,{className:(0,a.Z)({navbar__item:!r&&!o,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...a}=e;const{activeDoc:o}=(0,ze.Iw)(r),i=(0,Be.vY)(t,r),s=o?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(oe,{exact:!0,...a,isActive:()=>s||!!o?.sidebar&&o.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...a}=e;const{activeDoc:o}=(0,ze.Iw)(r),i=(0,Be.oz)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(oe,{exact:!0,...a,isActive:()=>o?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...a}=e;const o=(0,Be.lO)(r)[0],i=t??o.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(o).path;return(0,u.jsx)(oe,{...a,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:a,dropdownItemsAfter:o,...i}=e;const{search:c,hash:d}=(0,s.TH)(),p=(0,ze.Iw)(n),f=(0,ze.gB)(n),{savePreferredVersionName:m}=(0,$e.J)(n),h=[...a,...f.map((e=>{const t=p.alternateDocVersions[e.name]??Ue(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...o],g=(0,Be.lO)(n)[0],b=t&&h.length>1?(0,l.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,v=t&&h.length>1?void 0:Ue(g).path;return h.length<=1?(0,u.jsx)(oe,{...i,mobile:t,label:b,to:v,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:b,to:v,items:h,isActive:r?()=>!1:void 0})}};function He(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),a=qe[r];if(!a)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(a,{...n})}function Ze(){const e=(0,A.e)(),t=(0,x.L)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(He,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Ge(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(l.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function Ve(){const e=0===(0,x.L)().navbar.items.length,t=D();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(Ge,{onClick:()=>t.hide()}),t.content]})}function We(){const e=(0,A.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(M,{header:(0,u.jsx)(K,{}),primaryMenu:(0,u.jsx)(Ze,{}),secondaryMenu:(0,u.jsx)(Ve,{})}):null}const Qe={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Ke(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,a.Z)("navbar-sidebar__backdrop",e.className)})}function Ye(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,x.L)(),i=(0,A.e)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,L.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i<o.current)return void n(!0);if(a.current)return void(a.current=!1);const s=r?.scrollY,l=document.documentElement.scrollHeight-o.current,c=window.innerHeight;s&&i>=s?n(!1):i+c<l&&n(!0)})),(0,c.S)((t=>{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,l.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,a.Z)("navbar","navbar--fixed-top",n&&[Qe.navbarHideable,!d&&Qe.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(Ke,{onClick:i.toggle}),(0,u.jsx)(We,{})]})}var Xe=n(8780);const Je={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function et(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(l.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function tt(e){let{error:t}=e;const n=(0,Xe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Je.errorBoundaryError,children:n})}class nt extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const rt="right";function at(e){let{width:t=30,height:n=30,className:r,...a}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...a,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function ot(){const{toggle:e,shown:t}=(0,A.e)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,l.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(at,{})})}const it={colorModeToggle:"colorModeToggle_DEke"};function st(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(nt,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(He,{...e})},t)))})}function lt(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function ct(){const e=(0,A.e)(),t=(0,x.L)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??rt)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),a=t.find((e=>"search"===e.type));return(0,u.jsx)(lt,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(ot,{}),(0,u.jsx)(W,{}),(0,u.jsx)(st,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(st,{items:r}),(0,u.jsx)(G,{className:it.colorModeToggle}),!a&&(0,u.jsx)(Fe,{children:(0,u.jsx)(De,{})})]})})}function ut(){return(0,u.jsx)(Ye,{children:(0,u.jsx)(ct,{})})}function dt(e){let{item:t}=e;const{to:n,href:r,label:a,prependBaseUrlToHref:o,...i}=t,s=(0,X.Z)(n),l=(0,X.Z)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Y.Z,{className:"footer__link-item",...r?{href:o?l:r}:{to:s},...i,children:[a,r&&!(0,J.Z)(r)&&(0,u.jsx)(te.Z,{})]})}function pt(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(dt,{item:t})},t.href??t.to)}function ft(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(pt,{item:e},t)))})]})}function mt(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(ft,{column:e},t)))})}function ht(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function gt(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(dt,{item:t})}function bt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(gt,{item:e}),t.length!==n+1&&(0,u.jsx)(ht,{})]},n)))})})}function vt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(mt,{columns:t}):(0,u.jsx)(bt,{links:t})}var yt=n(9965);const xt={footerLogoLink:"footerLogoLink_BH7S"};function wt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(yt.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function kt(e){let{logo:t}=e;return t.href?(0,u.jsx)(Y.Z,{href:t.href,className:xt.footerLogoLink,target:t.target,children:(0,u.jsx)(wt,{logo:t})}):(0,u.jsx)(wt,{logo:t})}function St(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function _t(e){let{style:t,links:n,logo:r,copyright:o}=e;return(0,u.jsx)("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||o)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),o]})]})})}function Et(){const{footer:e}=(0,x.L)();if(!e)return null;const{copyright:t,links:n,logo:r,style:a}=e;return(0,u.jsx)(_t,{style:a,links:n&&n.length>0&&(0,u.jsx)(vt,{links:n}),logo:r&&(0,u.jsx)(kt,{logo:r}),copyright:t&&(0,u.jsx)(St,{copyright:t})})}const Ct=r.memo(Et),Tt=(0,R.Qc)([F.S,w.pl,L.OC,$e.L5,i.VC,function(e){let{children:t}=e;return(0,u.jsx)(N.n2,{children:(0,u.jsx)(A.M,{children:(0,u.jsx)(O,{children:t})})})}]);function jt(e){let{children:t}=e;return(0,u.jsx)(Tt,{children:t})}var At=n(2503);function Lt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(At.Z,{as:"h1",className:"hero__title",children:(0,u.jsx)(l.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(et,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(tt,{error:t})})]})})})}const Rt={mainWrapper:"mainWrapper_z2l0"};function Nt(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:l}=e;return(0,b.t)(),(0,u.jsxs)(jt,{children:[(0,u.jsx)(i.d,{title:s,description:l}),(0,u.jsx)(y,{}),(0,u.jsx)(j,{}),(0,u.jsx)(ut,{}),(0,u.jsx)("div",{id:d,className:(0,a.Z)(g.k.wrapper.main,Rt.mainWrapper,r),children:(0,u.jsx)(o.Z,{fallback:e=>(0,u.jsx)(Lt,{...e}),children:t})}),!n&&(0,u.jsx)(Ct,{})]})}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});n(7294);var r=n(3692),a=n(4996),o=n(2263),i=n(6668),s=n(9965),l=n(5893);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,a.Z)(t.src),dark:(0,a.Z)(t.srcDark||t.src)},i=(0,l.jsx)(s.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,l.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,o.Z)(),{navbar:{title:n,logo:s}}=(0,i.L)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,a.Z)(s?.href||"/"),m=n?"":t,h=s?.alt??m;return(0,l.jsxs)(r.Z,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,l.jsx)(c,{logo:s,alt:h,imageClassName:u}),null!=n&&(0,l.jsx)("b",{className:d,children:n})]})}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});n(7294);var r=n(5742),a=n(5893);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return(0,a.jsxs)(r.Z,{children:[t&&(0,a.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,a.jsx)("meta",{name:"docusaurus_version",content:n}),o&&(0,a.jsx)("meta",{name:"docusaurus_tag",content:o}),i&&(0,a.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,a.jsx)("meta",{name:"docsearch:version",content:n}),o&&(0,a.jsx)("meta",{name:"docsearch:docusaurus_tag",content:o})]})}},9965:(e,t,n)=>{"use strict";n.d(t,{Z:()=>u});var r=n(7294),a=n(512),o=n(2389),i=n(2949);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var l=n(5893);function c(e){let{className:t,children:n}=e;const c=(0,o.Z)(),{colorMode:u}=(0,i.I)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const o=n({theme:e,className:(0,a.Z)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,l.jsx)(r.Fragment,{children:o},e)}))})}function u(e){const{sources:t,className:n,alt:r,...a}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:o}=e;return(0,l.jsx)("img",{src:t[n],alt:r,className:o,...a})}})}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>c,z:()=>b});var r=n(7294),a=n(412),o=n(469),i=n(1442),s=n(5893);const l="ease-in-out";function c(e){let{initialState:t}=e;const[n,a]=(0,r.useState)(t??!1),o=(0,r.useCallback)((()=>{a((e=>!e))}),[]);return{collapsed:n,setCollapsed:a,toggleCollapsed:o}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:a}=e;const o=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=a?.duration??function(e){if((0,i.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${a?.easing??l}`,height:`${t}px`}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return p(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,a])}function m(e){if(!a.Z.canUseDOM)return e?u:d}function h(e){let{as:t="div",collapsed:n,children:a,animation:o,onCollapseTransitionEnd:i,className:l,disableSSRStyle:c}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:o}),(0,s.jsx)(t,{ref:u,style:c?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:l,children:a})}function g(e){let{collapsed:t,...n}=e;const[a,i]=(0,r.useState)(!t),[l,c]=(0,r.useState)(t);return(0,o.Z)((()=>{t||i(!0)}),[t]),(0,o.Z)((()=>{a&&c(t)}),[a,t]),a?(0,s.jsx)(h,{...n,collapsed:l}):null}function b(e){let{lazy:t,...n}=e;const r=t?g:h;return(0,s.jsx)(r,{...n})}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>h,pl:()=>m});var r=n(7294),a=n(2389),o=n(12),i=n(902),s=n(6668),l=n(5893);const c=(0,o.WA)("docusaurus.announcement.dismiss"),u=(0,o.WA)("docusaurus.announcement.id"),d=()=>"true"===c.get(),p=e=>c.set(String(e)),f=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{o(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(){const e=(0,r.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>b,S:()=>g});var r=n(7294),a=n(412),o=n(902),i=n(12),s=n(6668),l=n(5893);const c=r.createContext(void 0),u="theme",d=(0,i.WA)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,m=e=>a.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),h=e=>{d.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[a,o]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(o(t),a&&h(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(a))}),[a]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:a,setColorMode:i,get isDarkTheme(){return a===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[a,i])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(c);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>y,L5:()=>b,Oh:()=>x});var r=n(7294),a=n(143),o=n(9935),i=n(6668),s=n(2802),l=n(902),c=n(12),u=n(5893);const d=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.WA)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const m=r.createContext(null);function h(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=p.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=h();return(0,u.jsx)(m.Provider,{value:n,children:t})}function b(e){let{children:t}=e;return s.cE?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function v(){const e=(0,r.useContext)(m);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=v(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function x(){const e=(0,a._r)(),[t]=v();function n(n){const r=e[n],{preferredVersionName:a}=t[n];return r.versions.find((e=>e.name===a))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>c,b:()=>l});var r=n(7294),a=n(902),o=n(5893);const i=Symbol("EmptyContext"),s=r.createContext(i);function l(e){let{children:t,name:n,items:a}=e;const i=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return(0,o.jsx)(s.Provider,{value:i,children:t})}function c(){const e=(0,r.useContext)(s);if(e===i)throw new a.i6("DocsSidebarProvider");return e}},4477:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,q:()=>s});var r=n(7294),a=n(902),o=n(5893);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,o.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(null===e)throw new a.i6("DocsVersionProvider");return e}},3163:(e,t,n)=>{"use strict";n.d(t,{M:()=>p,e:()=>f});var r=n(7294),a=n(3102),o=n(7524),i=n(1980),s=n(6668),l=n(902),c=n(5893);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,s.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[l,c]=(0,r.useState)(!1);(0,i.Rb)((()=>{if(l)return c(!1),!1}));const u=(0,r.useCallback)((()=>{c((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function p(e){let{children:t}=e;const n=d();return(0,c.jsx)(u.Provider,{value:n,children:t})}function f(){const e=r.useContext(u);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>l,Zo:()=>c,n2:()=>s});var r=n(7294),a=n(902),o=n(5893);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,o.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const o=(0,r.useContext)(i);if(!o)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,s]=o,l=(0,a.Ql)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},6177:(e,t,n)=>{"use strict";n.d(t,{K:()=>s,M:()=>l});var r=n(7294),a=n(2263),o=n(1980);const i="q";function s(){return(0,o.Nc)(i)}function l(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,a.Z)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>`${e}${n}?${i}=${encodeURIComponent(t)}`),[e,n])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>s});var r=n(7294),a=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!a.Z.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?o.desktop:o.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},1442:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>r})},2802:(e,t,n)=>{"use strict";n.d(t,{LM:()=>f,_F:()=>g,cE:()=>p,SN:()=>_,lO:()=>w,vY:()=>S,oz:()=>k,s1:()=>x,f:()=>v});var r=n(7294),a=n(6550),o=n(8790),i=n(143),s=n(373),l=n(4477),c=n(1116);function u(e){return Array.from(new Set(e))}var d=n(8596);const p=!!i._r;function f(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=f(t);if(e)return e}}(e):void 0:e.href}const m=(e,t)=>void 0!==e&&(0,d.Mg)(e,t),h=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?m(e.href,t):"category"===e.type&&(m(e.href,t)||h(e.items,t))}function b(e,t){switch(e.type){case"category":return g(e,t)||e.items.some((e=>b(e,t)));case"link":return!e.unlisted||g(e,t);default:return!0}}function v(e,t){return(0,r.useMemo)((()=>e.filter((e=>b(e,t)))),[e,t])}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,d.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,d.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function x(){const e=(0,c.V)(),{pathname:t}=(0,a.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?y({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>u([t,n,a].filter(Boolean))),[t,n,a])}function k(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function S(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${u(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function _(e){let{route:t}=e;const n=(0,a.TH)(),r=(0,l.E)(),i=t.routes,s=i.find((e=>(0,a.LX)(n.pathname,e)));if(!s)return null;const c=s.sidebar,u=c?r.docsSidebars[c]:void 0;return{docElement:(0,o.H)(i),sidebarName:c,sidebarItems:u}}},2128:(e,t,n)=>{"use strict";n.d(t,{p:()=>a});var r=n(2263);function a(e){const{siteConfig:t}=(0,r.Z)(),{title:n,titleDelimiter:a}=t;return e?.trim().length?`${e.trim()} ${a} ${n}`:n}},1980:(e,t,n)=>{"use strict";n.d(t,{Nc:()=>l,Rb:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){!function(e){const t=(0,a.k6)(),n=(0,o.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function s(e){return function(e){const t=(0,a.k6)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function l(e){const t=s(e)??"",n=function(){const e=(0,a.k6)();return(0,r.useCallback)(((t,n,r)=>{const a=new URLSearchParams(e.location.search);n?a.set(t,n):a.delete(t),(r?.push?e.push:e.replace)({search:a.toString()})}),[e])}();return[t,(0,r.useCallback)(((t,r)=>{n(e,t,r)}),[n,e])]}},833:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>d,VC:()=>m});var r=n(7294),a=n(512),o=n(5742),i=n(226);function s(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2128),u=n(5893);function d(e){let{title:t,description:n,keywords:r,image:a,children:i}=e;const s=(0,c.p)(t),{withBaseUrl:d}=(0,l.C)(),p=a?d(a,{absolute:!0}):void 0;return(0,u.jsxs)(o.Z,{children:[t&&(0,u.jsx)("title",{children:s}),t&&(0,u.jsx)("meta",{property:"og:title",content:s}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,u.jsx)("meta",{property:"og:image",content:p}),p&&(0,u.jsx)("meta",{name:"twitter:image",content:p}),i]})}const p=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(p),s=(0,a.Z)(i,t);return(0,u.jsxs)(p.Provider,{value:s,children:[(0,u.jsx)(o.Z,{children:(0,u.jsx)("html",{className:s})}),n]})}function m(e){let{children:t}=e;const n=s(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const o=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(f,{className:(0,a.Z)(r,o),children:t})}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>s,Qc:()=>u,Ql:()=>c,i6:()=>l,zX:()=>i});var r=n(7294),a=n(469),o=n(5893);function i(e){const t=(0,r.useRef)(e);return(0,a.Z)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,a.Z)((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?<name>\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,o.jsx)(o.Fragment,{children:e.reduceRight(((e,t)=>(0,o.jsx)(t,{children:e})),n)})}}},8022:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{F:()=>r})},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>c,RF:()=>p});var r=n(7294),a=n(412),o=n(2389),i=(n(469),n(902)),s=n(5893);const l=r.createContext(void 0);function c(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,s.jsx)(l.Provider,{value:n,children:t})}function u(){const e=(0,r.useContext)(l);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const d=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),a=(0,r.useRef)(d()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=d();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&a<e)&&(t=requestAnimationFrame(r),window.scrollTo(0,Math.floor(.85*(a-e))+e))}(),()=>t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>i,_q:()=>l,os:()=>s});var r=n(143),a=n(2263),o=n(373);const i="default";function s(e,t){return`docs-${e}-${t}`}function l(){const{i18n:e}=(0,a.Z)(),t=(0,r._r)(),n=(0,r.WS)(),l=(0,o.Oh)();const c=[i,...Object.keys(t).map((function(e){const r=n?.activePlugin.pluginId===e?n.activeVersion:void 0,a=l[e],o=t[e].versions.find((e=>e.isLast));return s(e,(r??a??o).name)}))];return{locale:e.currentLocale,tags:c}}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>l});n(7294);const r="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,i||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),i=!0),null}var t}let i=!1;const s={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=o(t?.persistence);return null===n?s:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>i});var r=n(2263),a=n(6550),o=n(8780);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.Z)(),{pathname:l}=(0,a.TH)(),c=(0,o.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},6278:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){const{siteConfig:{themeConfig:e}}=(0,r.Z)();return e}},239:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var r=n(7294),a=n(8022),o=n(4996),i=n(6278);function s(){const{withBaseUrl:e}=(0,o.C)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.L)();return(0,r.useCallback)((r=>{const o=new URL(r);if((0,a.F)(t,o.href))return r;const i=`${o.pathname+o.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},9318:(e,t,n)=>{"use strict";n.d(t,{lX:()=>x,q_:()=>C,ob:()=>f,PP:()=>j,Ep:()=>p});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r<a;n+=1,r+=1)e[n]=e[r];e.pop()}const i=function(e,t){void 0===t&&(t="");var n,r=e&&e.split("/")||[],i=t&&t.split("/")||[],s=e&&a(e),l=t&&a(t),c=s||l;if(e&&a(e)?i=r:r.length&&(i.pop(),i=i.concat(r)),!i.length)return"/";if(i.length){var u=i[i.length-1];n="."===u||".."===u||""===u}else n=!1;for(var d=0,p=i.length;p>=0;p--){var f=i[p];"."===f?o(i,p):".."===f?(o(i,p),d++):d&&(o(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var s=n(8776);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function f(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.forEach((function(e){return e.apply(void 0,n)}))}}}var h=!("undefined"==typeof window||!window.document||!window.document.createElement);function g(e,t){t(window.confirm(e))}var b="popstate",v="hashchange";function y(){try{return window.history.state||{}}catch(e){return{}}}function x(e){void 0===e&&(e={}),h||(0,s.Z)(!1);var t,n=window.history,a=(-1===(t=window.navigator.userAgent).indexOf("Android 2.")&&-1===t.indexOf("Android 4.0")||-1===t.indexOf("Mobile Safari")||-1!==t.indexOf("Chrome")||-1!==t.indexOf("Windows Phone"))&&window.history&&"pushState"in window.history,o=!(-1===window.navigator.userAgent.indexOf("Trident")),i=e,c=i.forceRefresh,x=void 0!==c&&c,w=i.getUserConfirmation,k=void 0===w?g:w,S=i.keyLength,_=void 0===S?6:S,E=e.basename?d(l(e.basename)):"";function C(e){var t=e||{},n=t.key,r=t.state,a=window.location,o=a.pathname+a.search+a.hash;return E&&(o=u(o,E)),f(o,r,n)}function T(){return Math.random().toString(36).substr(2,_)}var j=m();function A(e){(0,r.Z)($,e),$.length=n.length,j.notifyListeners($.location,$.action)}function L(e){(function(e){return void 0===e.state&&-1===navigator.userAgent.indexOf("CriOS")})(e)||P(C(e.state))}function R(){P(C(y()))}var N=!1;function P(e){if(N)N=!1,A();else{j.confirmTransitionTo(e,"POP",k,(function(t){t?A({action:"POP",location:e}):function(e){var t=$.location,n=I.indexOf(t.key);-1===n&&(n=0);var r=I.indexOf(e.key);-1===r&&(r=0);var a=n-r;a&&(N=!0,M(a))}(e)}))}}var O=C(y()),I=[O.key];function D(e){return E+p(e)}function M(e){n.go(e)}var F=0;function z(e){1===(F+=e)&&1===e?(window.addEventListener(b,L),o&&window.addEventListener(v,R)):0===F&&(window.removeEventListener(b,L),o&&window.removeEventListener(v,R))}var B=!1;var $={length:n.length,action:"POP",location:O,createHref:D,push:function(e,t){var r="PUSH",o=f(e,t,T(),$.location);j.confirmTransitionTo(o,r,k,(function(e){if(e){var t=D(o),i=o.key,s=o.state;if(a)if(n.pushState({key:i,state:s},null,t),x)window.location.href=t;else{var l=I.indexOf($.location.key),c=I.slice(0,l+1);c.push(o.key),I=c,A({action:r,location:o})}else window.location.href=t}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,T(),$.location);j.confirmTransitionTo(o,r,k,(function(e){if(e){var t=D(o),i=o.key,s=o.state;if(a)if(n.replaceState({key:i,state:s},null,t),x)window.location.replace(t);else{var l=I.indexOf($.location.key);-1!==l&&(I[l]=o.key),A({action:r,location:o})}else window.location.replace(t)}}))},go:M,goBack:function(){M(-1)},goForward:function(){M(1)},block:function(e){void 0===e&&(e=!1);var t=j.setPrompt(e);return B||(z(1),B=!0),function(){return B&&(B=!1,z(-1)),t()}},listen:function(e){var t=j.appendListener(e);return z(1),function(){z(-1),t()}}};return $}var w="hashchange",k={hashbang:{encodePath:function(e){return"!"===e.charAt(0)?e:"!/"+c(e)},decodePath:function(e){return"!"===e.charAt(0)?e.substr(1):e}},noslash:{encodePath:c,decodePath:l},slash:{encodePath:l,decodePath:l}};function S(e){var t=e.indexOf("#");return-1===t?e:e.slice(0,t)}function _(){var e=window.location.href,t=e.indexOf("#");return-1===t?"":e.substring(t+1)}function E(e){window.location.replace(S(window.location.href)+"#"+e)}function C(e){void 0===e&&(e={}),h||(0,s.Z)(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),a=n.getUserConfirmation,o=void 0===a?g:a,i=n.hashType,c=void 0===i?"slash":i,b=e.basename?d(l(e.basename)):"",v=k[c],y=v.encodePath,x=v.decodePath;function C(){var e=x(_());return b&&(e=u(e,b)),f(e)}var T=m();function j(e){(0,r.Z)(B,e),B.length=t.length,T.notifyListeners(B.location,B.action)}var A=!1,L=null;function R(){var e,t,n=_(),r=y(n);if(n!==r)E(r);else{var a=C(),i=B.location;if(!A&&(t=a,(e=i).pathname===t.pathname&&e.search===t.search&&e.hash===t.hash))return;if(L===p(a))return;L=null,function(e){if(A)A=!1,j();else{var t="POP";T.confirmTransitionTo(e,t,o,(function(n){n?j({action:t,location:e}):function(e){var t=B.location,n=I.lastIndexOf(p(t));-1===n&&(n=0);var r=I.lastIndexOf(p(e));-1===r&&(r=0);var a=n-r;a&&(A=!0,D(a))}(e)}))}}(a)}}var N=_(),P=y(N);N!==P&&E(P);var O=C(),I=[p(O)];function D(e){t.go(e)}var M=0;function F(e){1===(M+=e)&&1===e?window.addEventListener(w,R):0===M&&window.removeEventListener(w,R)}var z=!1;var B={length:t.length,action:"POP",location:O,createHref:function(e){var t=document.querySelector("base"),n="";return t&&t.getAttribute("href")&&(n=S(window.location.href)),n+"#"+y(b+p(e))},push:function(e,t){var n="PUSH",r=f(e,void 0,void 0,B.location);T.confirmTransitionTo(r,n,o,(function(e){if(e){var t=p(r),a=y(b+t);if(_()!==a){L=t,function(e){window.location.hash=e}(a);var o=I.lastIndexOf(p(B.location)),i=I.slice(0,o+1);i.push(t),I=i,j({action:n,location:r})}else j()}}))},replace:function(e,t){var n="REPLACE",r=f(e,void 0,void 0,B.location);T.confirmTransitionTo(r,n,o,(function(e){if(e){var t=p(r),a=y(b+t);_()!==a&&(L=t,E(a));var o=I.indexOf(p(B.location));-1!==o&&(I[o]=t),j({action:n,location:r})}}))},go:D,goBack:function(){D(-1)},goForward:function(){D(1)},block:function(e){void 0===e&&(e=!1);var t=T.setPrompt(e);return z||(F(1),z=!0),function(){return z&&(z=!1,F(-1)),t()}},listen:function(e){var t=T.appendListener(e);return F(1),function(){F(-1),t()}}};return B}function T(e,t,n){return Math.min(Math.max(e,t),n)}function j(e){void 0===e&&(e={});var t=e,n=t.getUserConfirmation,a=t.initialEntries,o=void 0===a?["/"]:a,i=t.initialIndex,s=void 0===i?0:i,l=t.keyLength,c=void 0===l?6:l,u=m();function d(e){(0,r.Z)(x,e),x.length=x.entries.length,u.notifyListeners(x.location,x.action)}function h(){return Math.random().toString(36).substr(2,c)}var g=T(s,0,o.length-1),b=o.map((function(e){return f(e,void 0,"string"==typeof e?h():e.key||h())})),v=p;function y(e){var t=T(x.index+e,0,x.entries.length-1),r=x.entries[t];u.confirmTransitionTo(r,"POP",n,(function(e){e?d({action:"POP",location:r,index:t}):d()}))}var x={length:b.length,action:"POP",location:b[g],index:g,entries:b,createHref:v,push:function(e,t){var r="PUSH",a=f(e,t,h(),x.location);u.confirmTransitionTo(a,r,n,(function(e){if(e){var t=x.index+1,n=x.entries.slice(0);n.length>t?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=f(e,t,h(),x.location);u.confirmTransitionTo(a,r,n,(function(e){e&&(x.entries[x.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=x.index+e;return t>=0&&t<x.entries.length},block:function(e){return void 0===e&&(e=!1),u.setPrompt(e)},listen:function(e){return u.appendListener(e)}};return x}},8679:(e,t,n)=>{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||a}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=f(n);a&&a!==m&&e(t,a,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),h=l(n),g=0;g<i.length;++g){var b=i[g];if(!(o[b]||r&&r[b]||h&&h[b]||s&&s[b])){var v=p(n,b);try{c(t,b,v)}catch(y){}}}}return t}},1143:e=>{"use strict";e.exports=function(e,t,n,r,a,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,a,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function a(e,t,n){return e<t?t:e>n?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(r.barSelector),u=r.speed,d=r.easing;return o.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&f(a),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},9901:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to <a href="https://webplatform.github.io/docs/">WebPlatform.org documentation</a>. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (<code>.comment</code> can become <code>.namespace--comment</code>) or replace them with your defined ones (like <code>.editor__comment</code>). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the <code>highlightAll</code> and <code>highlightAllUnder</code> methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6854:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,s=i.length;-1!==n.code.indexOf(a=t(r,s));)++s;return i[s]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l<s.length&&!(a>=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[a],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(r,u),m=p.indexOf(f);if(m>-1){++a;var h=p.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=p.substring(m+f.length),v=[];h&&v.push.apply(v,i([h])),v.push(g),b&&v.push.apply(v,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(v)):c.content=v}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(Prism)},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n]]=!0;return t}function r(e){var n={},r=[];function a(r,o){if(!(r in n)){o.push(r);var i=o.indexOf(r);if(i<o.length-1)throw new Error("Circular dependency: "+o.slice(i).join(" -> "));var s={},l=e[r];if(l){function c(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in s))for(var i in a(t,o),s[t]=!0,n[t])s[i]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[r]=s,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,s){var l=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),c=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(l);i=i.map(c),s=(s||[]).map(c);var u=n(i),d=n(s);i.forEach((function e(n){var r=l[n];t(r&&r.require,(function(t){t in d||(u[t]=!0,e(t))}))}));for(var p,f=r(l),m=u;a(m);){for(var h in p={},m){var g=l[h];t(g&&g.modify,(function(e){e in d&&(p[e]=!0)}))}for(var b in d)if(!(b in u))for(var v in f(b))if(v in u){p[b]=!0;break}for(var y in m=p)u[y]=!0}var x={getIds:function(){var e=[];return x.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,s={},l={};function c(e){if(e in s)return s[e];l[e]=!0;var a,u=[];for(var d in t(e))d in n&&u.push(d);if(0===u.length)a=r(e);else{var p=i(u.map((function(e){var t=c(e);return delete l[e],t})));o?a=o(p,(function(){return r(e)})):r(e)}return s[e]=a}for(var u in n)c(u);var d=[];for(var p in l)d.push(s[p]);return i(d)}(f,u,t,n)}};return x}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(3840);function o(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var i=new Set,s={};function l(e,t){c(e,t),c(e+"Capture",t)}function c(e,t){for(s[e]=t,e=0;e<t.length;e++)i.add(t[e])}var u=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),d=Object.prototype.hasOwnProperty,p=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,f={},m={};function h(e,t,n,r,a,o,i){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=a,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o,this.removeEmptyString=i}var g={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){g[e]=new h(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];g[t]=new h(t,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){g[e]=new h(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){g[e]=new h(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){g[e]=new h(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){g[e]=new h(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){g[e]=new h(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){g[e]=new h(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){g[e]=new h(e,5,!1,e.toLowerCase(),null,!1,!1)}));var b=/[\-:]([a-z])/g;function v(e){return e[1].toUpperCase()}function y(e,t,n,r){var a=g.hasOwnProperty(t)?g[t]:null;(null!==a?0!==a.type:r||!(2<t.length)||"o"!==t[0]&&"O"!==t[0]||"n"!==t[1]&&"N"!==t[1])&&(function(e,t,n,r){if(null==t||function(e,t,n,r){if(null!==n&&0===n.type)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==n?!n.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,t,n,r))return!0;if(r)return!1;if(null!==n)switch(n.type){case 3:return!t;case 4:return!1===t;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}(t,n,a,r)&&(n=null),r||null===a?function(e){return!!d.call(m,e)||!d.call(f,e)&&(p.test(e)?m[e]=!0:(f[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):a.mustUseProperty?e[a.propertyName]=null===n?3!==a.type&&"":n:(t=a.attributeName,r=a.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(a=a.type)||4===a&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(b,v);g[t]=new h(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(b,v);g[t]=new h(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(b,v);g[t]=new h(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){g[e]=new h(e,1,!1,e.toLowerCase(),null,!1,!1)})),g.xlinkHref=new h("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){g[e]=new h(e,1,!1,e.toLowerCase(),null,!0,!0)}));var x=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,w=Symbol.for("react.element"),k=Symbol.for("react.portal"),S=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),E=Symbol.for("react.profiler"),C=Symbol.for("react.provider"),T=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),A=Symbol.for("react.suspense"),L=Symbol.for("react.suspense_list"),R=Symbol.for("react.memo"),N=Symbol.for("react.lazy");Symbol.for("react.scope"),Symbol.for("react.debug_trace_mode");var P=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden"),Symbol.for("react.cache"),Symbol.for("react.tracing_marker");var O=Symbol.iterator;function I(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=O&&e[O]||e["@@iterator"])?e:null}var D,M=Object.assign;function F(e){if(void 0===D)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);D=t&&t[1]||""}return"\n"+D+e}var z=!1;function B(e,t){if(!e||z)return"";z=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(c){var r=c}Reflect.construct(e,[],t)}else{try{t.call()}catch(c){r=c}e.call(t.prototype)}else{try{throw Error()}catch(c){r=c}e()}}catch(c){if(c&&r&&"string"==typeof c.stack){for(var a=c.stack.split("\n"),o=r.stack.split("\n"),i=a.length-1,s=o.length-1;1<=i&&0<=s&&a[i]!==o[s];)s--;for(;1<=i&&0<=s;i--,s--)if(a[i]!==o[s]){if(1!==i||1!==s)do{if(i--,0>--s||a[i]!==o[s]){var l="\n"+a[i].replace(" at new "," at ");return e.displayName&&l.includes("<anonymous>")&&(l=l.replace("<anonymous>",e.displayName)),l}}while(1<=i&&0<=s);break}}}finally{z=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?F(e):""}function $(e){switch(e.tag){case 5:return F(e.type);case 16:return F("Lazy");case 13:return F("Suspense");case 19:return F("SuspenseList");case 0:case 2:case 15:return e=B(e.type,!1);case 11:return e=B(e.type.render,!1);case 1:return e=B(e.type,!0);default:return""}}function U(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case S:return"Fragment";case k:return"Portal";case E:return"Profiler";case _:return"StrictMode";case A:return"Suspense";case L:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case T:return(e.displayName||"Context")+".Consumer";case C:return(e._context.displayName||"Context")+".Provider";case j:var t=e.render;return(e=e.displayName)||(e=""!==(e=t.displayName||t.name||"")?"ForwardRef("+e+")":"ForwardRef"),e;case R:return null!==(t=e.displayName||null)?t:U(e.type)||"Memo";case N:t=e._payload,e=e._init;try{return U(e(t))}catch(n){}}return null}function q(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=(e=t.render).displayName||e.name||"",t.displayName||(""!==e?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return U(t);case 8:return t===_?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t}return null}function H(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function Z(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function G(e){e._valueTracker||(e._valueTracker=function(e){var t=Z(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var a=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(e){r=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function V(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Z(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function W(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Q(e,t){var n=t.checked;return M({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function K(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=H(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function Y(e,t){null!=(t=t.checked)&&y(e,"checked",t,!1)}function X(e,t){Y(e,t);var n=H(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ee(e,t.type,n):t.hasOwnProperty("defaultValue")&&ee(e,t.type,H(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function J(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ee(e,t,n){"number"===t&&W(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var te=Array.isArray;function ne(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a<n.length;a++)t["$"+n[a]]=!0;for(n=0;n<e.length;n++)a=t.hasOwnProperty("$"+e[n].value),e[n].selected!==a&&(e[n].selected=a),a&&r&&(e[n].defaultSelected=!0)}else{for(n=""+H(n),t=null,a=0;a<e.length;a++){if(e[a].value===n)return e[a].selected=!0,void(r&&(e[a].defaultSelected=!0));null!==t||e[a].disabled||(t=e[a])}null!==t&&(t.selected=!0)}}function re(e,t){if(null!=t.dangerouslySetInnerHTML)throw Error(o(91));return M({},t,{value:void 0,defaultValue:void 0,children:""+e._wrapperState.initialValue})}function ae(e,t){var n=t.value;if(null==n){if(n=t.children,t=t.defaultValue,null!=n){if(null!=t)throw Error(o(92));if(te(n)){if(1<n.length)throw Error(o(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:H(n)}}function oe(e,t){var n=H(t.value),r=H(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function ie(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}function se(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function le(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?se(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var ce,ue,de=(ue=function(e,t){if("http://www.w3.org/2000/svg"!==e.namespaceURI||"innerHTML"in e)e.innerHTML=t;else{for((ce=ce||document.createElement("div")).innerHTML="<svg>"+t.valueOf().toString()+"</svg>",t=ce.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction((function(){return ue(e,t)}))}:ue);function pe(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var fe={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},me=["Webkit","ms","Moz","O"];function he(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||fe.hasOwnProperty(e)&&fe[e]?(""+t).trim():t+"px"}function ge(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),a=he(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}Object.keys(fe).forEach((function(e){me.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),fe[t]=fe[e]}))}));var be=M({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ve(e,t){if(t){if(be[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(o(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(o(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(o(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(o(62))}}function ye(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var xe=null;function we(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var ke=null,Se=null,_e=null;function Ee(e){if(e=ya(e)){if("function"!=typeof ke)throw Error(o(280));var t=e.stateNode;t&&(t=wa(t),ke(e.stateNode,e.type,t))}}function Ce(e){Se?_e?_e.push(e):_e=[e]:Se=e}function Te(){if(Se){var e=Se,t=_e;if(_e=Se=null,Ee(e),t)for(e=0;e<t.length;e++)Ee(t[e])}}function je(e,t){return e(t)}function Ae(){}var Le=!1;function Re(e,t,n){if(Le)return e(t,n);Le=!0;try{return je(e,t,n)}finally{Le=!1,(null!==Se||null!==_e)&&(Ae(),Te())}}function Ne(e,t){var n=e.stateNode;if(null===n)return null;var r=wa(n);if(null===r)return null;n=r[t];e:switch(t){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(r=!r.disabled)||(r=!("button"===(e=e.type)||"input"===e||"select"===e||"textarea"===e)),e=!r;break e;default:e=!1}if(e)return null;if(n&&"function"!=typeof n)throw Error(o(231,t,typeof n));return n}var Pe=!1;if(u)try{var Oe={};Object.defineProperty(Oe,"passive",{get:function(){Pe=!0}}),window.addEventListener("test",Oe,Oe),window.removeEventListener("test",Oe,Oe)}catch(ue){Pe=!1}function Ie(e,t,n,r,a,o,i,s,l){var c=Array.prototype.slice.call(arguments,3);try{t.apply(n,c)}catch(u){this.onError(u)}}var De=!1,Me=null,Fe=!1,ze=null,Be={onError:function(e){De=!0,Me=e}};function $e(e,t,n,r,a,o,i,s,l){De=!1,Me=null,Ie.apply(Be,arguments)}function Ue(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do{0!=(4098&(t=e).flags)&&(n=t.return),e=t.return}while(e)}return 3===t.tag?n:null}function qe(e){if(13===e.tag){var t=e.memoizedState;if(null===t&&(null!==(e=e.alternate)&&(t=e.memoizedState)),null!==t)return t.dehydrated}return null}function He(e){if(Ue(e)!==e)throw Error(o(188))}function Ze(e){return null!==(e=function(e){var t=e.alternate;if(!t){if(null===(t=Ue(e)))throw Error(o(188));return t!==e?null:e}for(var n=e,r=t;;){var a=n.return;if(null===a)break;var i=a.alternate;if(null===i){if(null!==(r=a.return)){n=r;continue}break}if(a.child===i.child){for(i=a.child;i;){if(i===n)return He(a),e;if(i===r)return He(a),t;i=i.sibling}throw Error(o(188))}if(n.return!==r.return)n=a,r=i;else{for(var s=!1,l=a.child;l;){if(l===n){s=!0,n=a,r=i;break}if(l===r){s=!0,r=a,n=i;break}l=l.sibling}if(!s){for(l=i.child;l;){if(l===n){s=!0,n=i,r=a;break}if(l===r){s=!0,r=i,n=a;break}l=l.sibling}if(!s)throw Error(o(189))}}if(n.alternate!==r)throw Error(o(190))}if(3!==n.tag)throw Error(o(188));return n.stateNode.current===n?e:t}(e))?Ge(e):null}function Ge(e){if(5===e.tag||6===e.tag)return e;for(e=e.child;null!==e;){var t=Ge(e);if(null!==t)return t;e=e.sibling}return null}var Ve=a.unstable_scheduleCallback,We=a.unstable_cancelCallback,Qe=a.unstable_shouldYield,Ke=a.unstable_requestPaint,Ye=a.unstable_now,Xe=a.unstable_getCurrentPriorityLevel,Je=a.unstable_ImmediatePriority,et=a.unstable_UserBlockingPriority,tt=a.unstable_NormalPriority,nt=a.unstable_LowPriority,rt=a.unstable_IdlePriority,at=null,ot=null;var it=Math.clz32?Math.clz32:function(e){return e>>>=0,0===e?32:31-(st(e)/lt|0)|0},st=Math.log,lt=Math.LN2;var ct=64,ut=4194304;function dt(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return 4194240&e;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return 130023424&e;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function pt(e,t){var n=e.pendingLanes;if(0===n)return 0;var r=0,a=e.suspendedLanes,o=e.pingedLanes,i=268435455&n;if(0!==i){var s=i&~a;0!==s?r=dt(s):0!==(o&=i)&&(r=dt(o))}else 0!==(i=n&~a)?r=dt(i):0!==o&&(r=dt(o));if(0===r)return 0;if(0!==t&&t!==r&&0==(t&a)&&((a=r&-r)>=(o=t&-t)||16===a&&0!=(4194240&o)))return t;if(0!=(4&r)&&(r|=16&n),0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0<t;)a=1<<(n=31-it(t)),r|=e[n],t&=~a;return r}function ft(e,t){switch(e){case 1:case 2:case 4:return t+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;default:return-1}}function mt(e){return 0!==(e=-1073741825&e.pendingLanes)?e:1073741824&e?1073741824:0}function ht(){var e=ct;return 0==(4194240&(ct<<=1))&&(ct=64),e}function gt(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function bt(e,t,n){e.pendingLanes|=t,536870912!==t&&(e.suspendedLanes=0,e.pingedLanes=0),(e=e.eventTimes)[t=31-it(t)]=n}function vt(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-it(n),a=1<<r;a&t|e[r]&t&&(e[r]|=t),n&=~a}}var yt=0;function xt(e){return 1<(e&=-e)?4<e?0!=(268435455&e)?16:536870912:4:1}var wt,kt,St,_t,Et,Ct=!1,Tt=[],jt=null,At=null,Lt=null,Rt=new Map,Nt=new Map,Pt=[],Ot="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" ");function It(e,t){switch(e){case"focusin":case"focusout":jt=null;break;case"dragenter":case"dragleave":At=null;break;case"mouseover":case"mouseout":Lt=null;break;case"pointerover":case"pointerout":Rt.delete(t.pointerId);break;case"gotpointercapture":case"lostpointercapture":Nt.delete(t.pointerId)}}function Dt(e,t,n,r,a,o){return null===e||e.nativeEvent!==o?(e={blockedOn:t,domEventName:n,eventSystemFlags:r,nativeEvent:o,targetContainers:[a]},null!==t&&(null!==(t=ya(t))&&kt(t)),e):(e.eventSystemFlags|=r,t=e.targetContainers,null!==a&&-1===t.indexOf(a)&&t.push(a),e)}function Mt(e){var t=va(e.target);if(null!==t){var n=Ue(t);if(null!==n)if(13===(t=n.tag)){if(null!==(t=qe(n)))return e.blockedOn=t,void Et(e.priority,(function(){St(n)}))}else if(3===t&&n.stateNode.current.memoizedState.isDehydrated)return void(e.blockedOn=3===n.tag?n.stateNode.containerInfo:null)}e.blockedOn=null}function Ft(e){if(null!==e.blockedOn)return!1;for(var t=e.targetContainers;0<t.length;){var n=Qt(e.domEventName,e.eventSystemFlags,t[0],e.nativeEvent);if(null!==n)return null!==(t=ya(n))&&kt(t),e.blockedOn=n,!1;var r=new(n=e.nativeEvent).constructor(n.type,n);xe=r,n.target.dispatchEvent(r),xe=null,t.shift()}return!0}function zt(e,t,n){Ft(e)&&n.delete(t)}function Bt(){Ct=!1,null!==jt&&Ft(jt)&&(jt=null),null!==At&&Ft(At)&&(At=null),null!==Lt&&Ft(Lt)&&(Lt=null),Rt.forEach(zt),Nt.forEach(zt)}function $t(e,t){e.blockedOn===t&&(e.blockedOn=null,Ct||(Ct=!0,a.unstable_scheduleCallback(a.unstable_NormalPriority,Bt)))}function Ut(e){function t(t){return $t(t,e)}if(0<Tt.length){$t(Tt[0],e);for(var n=1;n<Tt.length;n++){var r=Tt[n];r.blockedOn===e&&(r.blockedOn=null)}}for(null!==jt&&$t(jt,e),null!==At&&$t(At,e),null!==Lt&&$t(Lt,e),Rt.forEach(t),Nt.forEach(t),n=0;n<Pt.length;n++)(r=Pt[n]).blockedOn===e&&(r.blockedOn=null);for(;0<Pt.length&&null===(n=Pt[0]).blockedOn;)Mt(n),null===n.blockedOn&&Pt.shift()}var qt=x.ReactCurrentBatchConfig,Ht=!0;function Zt(e,t,n,r){var a=yt,o=qt.transition;qt.transition=null;try{yt=1,Vt(e,t,n,r)}finally{yt=a,qt.transition=o}}function Gt(e,t,n,r){var a=yt,o=qt.transition;qt.transition=null;try{yt=4,Vt(e,t,n,r)}finally{yt=a,qt.transition=o}}function Vt(e,t,n,r){if(Ht){var a=Qt(e,t,n,r);if(null===a)Hr(e,t,r,Wt,n),It(e,r);else if(function(e,t,n,r,a){switch(t){case"focusin":return jt=Dt(jt,e,t,n,r,a),!0;case"dragenter":return At=Dt(At,e,t,n,r,a),!0;case"mouseover":return Lt=Dt(Lt,e,t,n,r,a),!0;case"pointerover":var o=a.pointerId;return Rt.set(o,Dt(Rt.get(o)||null,e,t,n,r,a)),!0;case"gotpointercapture":return o=a.pointerId,Nt.set(o,Dt(Nt.get(o)||null,e,t,n,r,a)),!0}return!1}(a,e,t,n,r))r.stopPropagation();else if(It(e,r),4&t&&-1<Ot.indexOf(e)){for(;null!==a;){var o=ya(a);if(null!==o&&wt(o),null===(o=Qt(e,t,n,r))&&Hr(e,t,r,Wt,n),o===a)break;a=o}null!==a&&r.stopPropagation()}else Hr(e,t,r,null,n)}}var Wt=null;function Qt(e,t,n,r){if(Wt=null,null!==(e=va(e=we(r))))if(null===(t=Ue(e)))e=null;else if(13===(n=t.tag)){if(null!==(e=qe(t)))return e;e=null}else if(3===n){if(t.stateNode.current.memoizedState.isDehydrated)return 3===t.tag?t.stateNode.containerInfo:null;e=null}else t!==e&&(e=null);return Wt=e,null}function Kt(e){switch(e){case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 1;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"toggle":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 4;case"message":switch(Xe()){case Je:return 1;case et:return 4;case tt:case nt:return 16;case rt:return 536870912;default:return 16}default:return 16}}var Yt=null,Xt=null,Jt=null;function en(){if(Jt)return Jt;var e,t,n=Xt,r=n.length,a="value"in Yt?Yt.value:Yt.textContent,o=a.length;for(e=0;e<r&&n[e]===a[e];e++);var i=r-e;for(t=1;t<=i&&n[r-t]===a[o-t];t++);return Jt=a.slice(e,1<t?1-t:void 0)}function tn(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,10===e&&(e=13),32<=e||13===e?e:0}function nn(){return!0}function rn(){return!1}function an(e){function t(t,n,r,a,o){for(var i in this._reactName=t,this._targetInst=r,this.type=n,this.nativeEvent=a,this.target=o,this.currentTarget=null,e)e.hasOwnProperty(i)&&(t=e[i],this[i]=t?t(a):a[i]);return this.isDefaultPrevented=(null!=a.defaultPrevented?a.defaultPrevented:!1===a.returnValue)?nn:rn,this.isPropagationStopped=rn,this}return M(t.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=nn)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=nn)},persist:function(){},isPersistent:nn}),t}var on,sn,ln,cn={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},un=an(cn),dn=M({},cn,{view:0,detail:0}),pn=an(dn),fn=M({},dn,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:En,button:0,buttons:0,relatedTarget:function(e){return void 0===e.relatedTarget?e.fromElement===e.srcElement?e.toElement:e.fromElement:e.relatedTarget},movementX:function(e){return"movementX"in e?e.movementX:(e!==ln&&(ln&&"mousemove"===e.type?(on=e.screenX-ln.screenX,sn=e.screenY-ln.screenY):sn=on=0,ln=e),on)},movementY:function(e){return"movementY"in e?e.movementY:sn}}),mn=an(fn),hn=an(M({},fn,{dataTransfer:0})),gn=an(M({},dn,{relatedTarget:0})),bn=an(M({},cn,{animationName:0,elapsedTime:0,pseudoElement:0})),vn=M({},cn,{clipboardData:function(e){return"clipboardData"in e?e.clipboardData:window.clipboardData}}),yn=an(vn),xn=an(M({},cn,{data:0})),wn={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},kn={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},Sn={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function _n(e){var t=this.nativeEvent;return t.getModifierState?t.getModifierState(e):!!(e=Sn[e])&&!!t[e]}function En(){return _n}var Cn=M({},dn,{key:function(e){if(e.key){var t=wn[e.key]||e.key;if("Unidentified"!==t)return t}return"keypress"===e.type?13===(e=tn(e))?"Enter":String.fromCharCode(e):"keydown"===e.type||"keyup"===e.type?kn[e.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:En,charCode:function(e){return"keypress"===e.type?tn(e):0},keyCode:function(e){return"keydown"===e.type||"keyup"===e.type?e.keyCode:0},which:function(e){return"keypress"===e.type?tn(e):"keydown"===e.type||"keyup"===e.type?e.keyCode:0}}),Tn=an(Cn),jn=an(M({},fn,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0})),An=an(M({},dn,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:En})),Ln=an(M({},cn,{propertyName:0,elapsedTime:0,pseudoElement:0})),Rn=M({},fn,{deltaX:function(e){return"deltaX"in e?e.deltaX:"wheelDeltaX"in e?-e.wheelDeltaX:0},deltaY:function(e){return"deltaY"in e?e.deltaY:"wheelDeltaY"in e?-e.wheelDeltaY:"wheelDelta"in e?-e.wheelDelta:0},deltaZ:0,deltaMode:0}),Nn=an(Rn),Pn=[9,13,27,32],On=u&&"CompositionEvent"in window,In=null;u&&"documentMode"in document&&(In=document.documentMode);var Dn=u&&"TextEvent"in window&&!In,Mn=u&&(!On||In&&8<In&&11>=In),Fn=String.fromCharCode(32),zn=!1;function Bn(e,t){switch(e){case"keyup":return-1!==Pn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $n(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Un=!1;var qn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Hn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!qn[e.type]:"textarea"===t}function Zn(e,t,n,r){Ce(r),0<(t=Gr(t,"onChange")).length&&(n=new un("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Gn=null,Vn=null;function Wn(e){Fr(e,0)}function Qn(e){if(V(xa(e)))return e}function Kn(e,t){if("change"===e)return t}var Yn=!1;if(u){var Xn;if(u){var Jn="oninput"in document;if(!Jn){var er=document.createElement("div");er.setAttribute("oninput","return;"),Jn="function"==typeof er.oninput}Xn=Jn}else Xn=!1;Yn=Xn&&(!document.documentMode||9<document.documentMode)}function tr(){Gn&&(Gn.detachEvent("onpropertychange",nr),Vn=Gn=null)}function nr(e){if("value"===e.propertyName&&Qn(Vn)){var t=[];Zn(t,Vn,e,we(e)),Re(Wn,t)}}function rr(e,t,n){"focusin"===e?(tr(),Vn=n,(Gn=t).attachEvent("onpropertychange",nr)):"focusout"===e&&tr()}function ar(e){if("selectionchange"===e||"keyup"===e||"keydown"===e)return Qn(Vn)}function or(e,t){if("click"===e)return Qn(t)}function ir(e,t){if("input"===e||"change"===e)return Qn(t)}var sr="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t};function lr(e,t){if(sr(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;var n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(r=0;r<n.length;r++){var a=n[r];if(!d.call(t,a)||!sr(e[a],t[a]))return!1}return!0}function cr(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function ur(e,t){var n,r=cr(e);for(e=0;r;){if(3===r.nodeType){if(n=e+r.textContent.length,e<=t&&n>=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=cr(r)}}function dr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?dr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function pr(){for(var e=window,t=W();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(r){n=!1}if(!n)break;t=W((e=t.contentWindow).document)}return t}function fr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}function mr(e){var t=pr(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&dr(n.ownerDocument.documentElement,n)){if(null!==r&&fr(n))if(t=r.start,void 0===(e=r.end)&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if((e=(t=n.ownerDocument||document)&&t.defaultView||window).getSelection){e=e.getSelection();var a=n.textContent.length,o=Math.min(r.start,a);r=void 0===r.end?o:Math.min(r.end,a),!e.extend&&o>r&&(a=r,r=o,o=a),a=ur(n,o);var i=ur(n,r);a&&i&&(1!==e.rangeCount||e.anchorNode!==a.node||e.anchorOffset!==a.offset||e.focusNode!==i.node||e.focusOffset!==i.offset)&&((t=t.createRange()).setStart(a.node,a.offset),e.removeAllRanges(),o>r?(e.addRange(t),e.extend(i.node,i.offset)):(t.setEnd(i.node,i.offset),e.addRange(t)))}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof n.focus&&n.focus(),n=0;n<t.length;n++)(e=t[n]).element.scrollLeft=e.left,e.element.scrollTop=e.top}}var hr=u&&"documentMode"in document&&11>=document.documentMode,gr=null,br=null,vr=null,yr=!1;function xr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;yr||null==gr||gr!==W(r)||("selectionStart"in(r=gr)&&fr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},vr&&lr(vr,r)||(vr=r,0<(r=Gr(br,"onSelect")).length&&(t=new un("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=gr)))}function wr(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var kr={animationend:wr("Animation","AnimationEnd"),animationiteration:wr("Animation","AnimationIteration"),animationstart:wr("Animation","AnimationStart"),transitionend:wr("Transition","TransitionEnd")},Sr={},_r={};function Er(e){if(Sr[e])return Sr[e];if(!kr[e])return e;var t,n=kr[e];for(t in n)if(n.hasOwnProperty(t)&&t in _r)return Sr[e]=n[t];return e}u&&(_r=document.createElement("div").style,"AnimationEvent"in window||(delete kr.animationend.animation,delete kr.animationiteration.animation,delete kr.animationstart.animation),"TransitionEvent"in window||delete kr.transitionend.transition);var Cr=Er("animationend"),Tr=Er("animationiteration"),jr=Er("animationstart"),Ar=Er("transitionend"),Lr=new Map,Rr="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Nr(e,t){Lr.set(e,t),l(t,[e])}for(var Pr=0;Pr<Rr.length;Pr++){var Or=Rr[Pr];Nr(Or.toLowerCase(),"on"+(Or[0].toUpperCase()+Or.slice(1)))}Nr(Cr,"onAnimationEnd"),Nr(Tr,"onAnimationIteration"),Nr(jr,"onAnimationStart"),Nr("dblclick","onDoubleClick"),Nr("focusin","onFocus"),Nr("focusout","onBlur"),Nr(Ar,"onTransitionEnd"),c("onMouseEnter",["mouseout","mouseover"]),c("onMouseLeave",["mouseout","mouseover"]),c("onPointerEnter",["pointerout","pointerover"]),c("onPointerLeave",["pointerout","pointerover"]),l("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),l("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),l("onBeforeInput",["compositionend","keypress","textInput","paste"]),l("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),l("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),l("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var Ir="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Dr=new Set("cancel close invalid load scroll toggle".split(" ").concat(Ir));function Mr(e,t,n){var r=e.type||"unknown-event";e.currentTarget=n,function(e,t,n,r,a,i,s,l,c){if($e.apply(this,arguments),De){if(!De)throw Error(o(198));var u=Me;De=!1,Me=null,Fe||(Fe=!0,ze=u)}}(r,t,void 0,e),e.currentTarget=null}function Fr(e,t){t=0!=(4&t);for(var n=0;n<e.length;n++){var r=e[n],a=r.event;r=r.listeners;e:{var o=void 0;if(t)for(var i=r.length-1;0<=i;i--){var s=r[i],l=s.instance,c=s.currentTarget;if(s=s.listener,l!==o&&a.isPropagationStopped())break e;Mr(a,s,c),o=l}else for(i=0;i<r.length;i++){if(l=(s=r[i]).instance,c=s.currentTarget,s=s.listener,l!==o&&a.isPropagationStopped())break e;Mr(a,s,c),o=l}}}if(Fe)throw e=ze,Fe=!1,ze=null,e}function zr(e,t){var n=t[ha];void 0===n&&(n=t[ha]=new Set);var r=e+"__bubble";n.has(r)||(qr(t,e,2,!1),n.add(r))}function Br(e,t,n){var r=0;t&&(r|=4),qr(n,e,r,t)}var $r="_reactListening"+Math.random().toString(36).slice(2);function Ur(e){if(!e[$r]){e[$r]=!0,i.forEach((function(t){"selectionchange"!==t&&(Dr.has(t)||Br(t,!1,e),Br(t,!0,e))}));var t=9===e.nodeType?e:e.ownerDocument;null===t||t[$r]||(t[$r]=!0,Br("selectionchange",!1,t))}}function qr(e,t,n,r){switch(Kt(t)){case 1:var a=Zt;break;case 4:a=Gt;break;default:a=Vt}n=a.bind(null,t,n,e),a=void 0,!Pe||"touchstart"!==t&&"touchmove"!==t&&"wheel"!==t||(a=!0),r?void 0!==a?e.addEventListener(t,n,{capture:!0,passive:a}):e.addEventListener(t,n,!0):void 0!==a?e.addEventListener(t,n,{passive:a}):e.addEventListener(t,n,!1)}function Hr(e,t,n,r,a){var o=r;if(0==(1&t)&&0==(2&t)&&null!==r)e:for(;;){if(null===r)return;var i=r.tag;if(3===i||4===i){var s=r.stateNode.containerInfo;if(s===a||8===s.nodeType&&s.parentNode===a)break;if(4===i)for(i=r.return;null!==i;){var l=i.tag;if((3===l||4===l)&&((l=i.stateNode.containerInfo)===a||8===l.nodeType&&l.parentNode===a))return;i=i.return}for(;null!==s;){if(null===(i=va(s)))return;if(5===(l=i.tag)||6===l){r=o=i;continue e}s=s.parentNode}}r=r.return}Re((function(){var r=o,a=we(n),i=[];e:{var s=Lr.get(e);if(void 0!==s){var l=un,c=e;switch(e){case"keypress":if(0===tn(n))break e;case"keydown":case"keyup":l=Tn;break;case"focusin":c="focus",l=gn;break;case"focusout":c="blur",l=gn;break;case"beforeblur":case"afterblur":l=gn;break;case"click":if(2===n.button)break e;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":l=mn;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":l=hn;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":l=An;break;case Cr:case Tr:case jr:l=bn;break;case Ar:l=Ln;break;case"scroll":l=pn;break;case"wheel":l=Nn;break;case"copy":case"cut":case"paste":l=yn;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":l=jn}var u=0!=(4&t),d=!u&&"scroll"===e,p=u?null!==s?s+"Capture":null:s;u=[];for(var f,m=r;null!==m;){var h=(f=m).stateNode;if(5===f.tag&&null!==h&&(f=h,null!==p&&(null!=(h=Ne(m,p))&&u.push(Zr(m,h,f)))),d)break;m=m.return}0<u.length&&(s=new l(s,c,null,n,a),i.push({event:s,listeners:u}))}}if(0==(7&t)){if(l="mouseout"===e||"pointerout"===e,(!(s="mouseover"===e||"pointerover"===e)||n===xe||!(c=n.relatedTarget||n.fromElement)||!va(c)&&!c[ma])&&(l||s)&&(s=a.window===a?a:(s=a.ownerDocument)?s.defaultView||s.parentWindow:window,l?(l=r,null!==(c=(c=n.relatedTarget||n.toElement)?va(c):null)&&(c!==(d=Ue(c))||5!==c.tag&&6!==c.tag)&&(c=null)):(l=null,c=r),l!==c)){if(u=mn,h="onMouseLeave",p="onMouseEnter",m="mouse","pointerout"!==e&&"pointerover"!==e||(u=jn,h="onPointerLeave",p="onPointerEnter",m="pointer"),d=null==l?s:xa(l),f=null==c?s:xa(c),(s=new u(h,m+"leave",l,n,a)).target=d,s.relatedTarget=f,h=null,va(a)===r&&((u=new u(p,m+"enter",c,n,a)).target=f,u.relatedTarget=d,h=u),d=h,l&&c)e:{for(p=c,m=0,f=u=l;f;f=Vr(f))m++;for(f=0,h=p;h;h=Vr(h))f++;for(;0<m-f;)u=Vr(u),m--;for(;0<f-m;)p=Vr(p),f--;for(;m--;){if(u===p||null!==p&&u===p.alternate)break e;u=Vr(u),p=Vr(p)}u=null}else u=null;null!==l&&Wr(i,s,l,u,!1),null!==c&&null!==d&&Wr(i,d,c,u,!0)}if("select"===(l=(s=r?xa(r):window).nodeName&&s.nodeName.toLowerCase())||"input"===l&&"file"===s.type)var g=Kn;else if(Hn(s))if(Yn)g=ir;else{g=ar;var b=rr}else(l=s.nodeName)&&"input"===l.toLowerCase()&&("checkbox"===s.type||"radio"===s.type)&&(g=or);switch(g&&(g=g(e,r))?Zn(i,g,n,a):(b&&b(e,s,r),"focusout"===e&&(b=s._wrapperState)&&b.controlled&&"number"===s.type&&ee(s,"number",s.value)),b=r?xa(r):window,e){case"focusin":(Hn(b)||"true"===b.contentEditable)&&(gr=b,br=r,vr=null);break;case"focusout":vr=br=gr=null;break;case"mousedown":yr=!0;break;case"contextmenu":case"mouseup":case"dragend":yr=!1,xr(i,n,a);break;case"selectionchange":if(hr)break;case"keydown":case"keyup":xr(i,n,a)}var v;if(On)e:{switch(e){case"compositionstart":var y="onCompositionStart";break e;case"compositionend":y="onCompositionEnd";break e;case"compositionupdate":y="onCompositionUpdate";break e}y=void 0}else Un?Bn(e,n)&&(y="onCompositionEnd"):"keydown"===e&&229===n.keyCode&&(y="onCompositionStart");y&&(Mn&&"ko"!==n.locale&&(Un||"onCompositionStart"!==y?"onCompositionEnd"===y&&Un&&(v=en()):(Xt="value"in(Yt=a)?Yt.value:Yt.textContent,Un=!0)),0<(b=Gr(r,y)).length&&(y=new xn(y,e,null,n,a),i.push({event:y,listeners:b}),v?y.data=v:null!==(v=$n(n))&&(y.data=v))),(v=Dn?function(e,t){switch(e){case"compositionend":return $n(t);case"keypress":return 32!==t.which?null:(zn=!0,Fn);case"textInput":return(e=t.data)===Fn&&zn?null:e;default:return null}}(e,n):function(e,t){if(Un)return"compositionend"===e||!On&&Bn(e,t)?(e=en(),Jt=Xt=Yt=null,Un=!1,e):null;switch(e){case"paste":default:return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1<t.char.length)return t.char;if(t.which)return String.fromCharCode(t.which)}return null;case"compositionend":return Mn&&"ko"!==t.locale?null:t.data}}(e,n))&&(0<(r=Gr(r,"onBeforeInput")).length&&(a=new xn("onBeforeInput","beforeinput",null,n,a),i.push({event:a,listeners:r}),a.data=v))}Fr(i,t)}))}function Zr(e,t,n){return{instance:e,listener:t,currentTarget:n}}function Gr(e,t){for(var n=t+"Capture",r=[];null!==e;){var a=e,o=a.stateNode;5===a.tag&&null!==o&&(a=o,null!=(o=Ne(e,n))&&r.unshift(Zr(e,o,a)),null!=(o=Ne(e,t))&&r.push(Zr(e,o,a))),e=e.return}return r}function Vr(e){if(null===e)return null;do{e=e.return}while(e&&5!==e.tag);return e||null}function Wr(e,t,n,r,a){for(var o=t._reactName,i=[];null!==n&&n!==r;){var s=n,l=s.alternate,c=s.stateNode;if(null!==l&&l===r)break;5===s.tag&&null!==c&&(s=c,a?null!=(l=Ne(n,o))&&i.unshift(Zr(n,l,s)):a||null!=(l=Ne(n,o))&&i.push(Zr(n,l,s))),n=n.return}0!==i.length&&e.push({event:t,listeners:i})}var Qr=/\r\n?/g,Kr=/\u0000|\uFFFD/g;function Yr(e){return("string"==typeof e?e:""+e).replace(Qr,"\n").replace(Kr,"")}function Xr(e,t,n){if(t=Yr(t),Yr(e)!==t&&n)throw Error(o(425))}function Jr(){}var ea=null,ta=null;function na(e,t){return"textarea"===e||"noscript"===e||"string"==typeof t.children||"number"==typeof t.children||"object"==typeof t.dangerouslySetInnerHTML&&null!==t.dangerouslySetInnerHTML&&null!=t.dangerouslySetInnerHTML.__html}var ra="function"==typeof setTimeout?setTimeout:void 0,aa="function"==typeof clearTimeout?clearTimeout:void 0,oa="function"==typeof Promise?Promise:void 0,ia="function"==typeof queueMicrotask?queueMicrotask:void 0!==oa?function(e){return oa.resolve(null).then(e).catch(sa)}:ra;function sa(e){setTimeout((function(){throw e}))}function la(e,t){var n=t,r=0;do{var a=n.nextSibling;if(e.removeChild(n),a&&8===a.nodeType)if("/$"===(n=a.data)){if(0===r)return e.removeChild(a),void Ut(t);r--}else"$"!==n&&"$?"!==n&&"$!"!==n||r++;n=a}while(n);Ut(t)}function ca(e){for(;null!=e;e=e.nextSibling){var t=e.nodeType;if(1===t||3===t)break;if(8===t){if("$"===(t=e.data)||"$!"===t||"$?"===t)break;if("/$"===t)return null}}return e}function ua(e){e=e.previousSibling;for(var t=0;e;){if(8===e.nodeType){var n=e.data;if("$"===n||"$!"===n||"$?"===n){if(0===t)return e;t--}else"/$"===n&&t++}e=e.previousSibling}return null}var da=Math.random().toString(36).slice(2),pa="__reactFiber$"+da,fa="__reactProps$"+da,ma="__reactContainer$"+da,ha="__reactEvents$"+da,ga="__reactListeners$"+da,ba="__reactHandles$"+da;function va(e){var t=e[pa];if(t)return t;for(var n=e.parentNode;n;){if(t=n[ma]||n[pa]){if(n=t.alternate,null!==t.child||null!==n&&null!==n.child)for(e=ua(e);null!==e;){if(n=e[pa])return n;e=ua(e)}return t}n=(e=n).parentNode}return null}function ya(e){return!(e=e[pa]||e[ma])||5!==e.tag&&6!==e.tag&&13!==e.tag&&3!==e.tag?null:e}function xa(e){if(5===e.tag||6===e.tag)return e.stateNode;throw Error(o(33))}function wa(e){return e[fa]||null}var ka=[],Sa=-1;function _a(e){return{current:e}}function Ea(e){0>Sa||(e.current=ka[Sa],ka[Sa]=null,Sa--)}function Ca(e,t){Sa++,ka[Sa]=e.current,e.current=t}var Ta={},ja=_a(Ta),Aa=_a(!1),La=Ta;function Ra(e,t){var n=e.type.contextTypes;if(!n)return Ta;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a,o={};for(a in n)o[a]=t[a];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function Na(e){return null!=(e=e.childContextTypes)}function Pa(){Ea(Aa),Ea(ja)}function Oa(e,t,n){if(ja.current!==Ta)throw Error(o(168));Ca(ja,t),Ca(Aa,n)}function Ia(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var a in r=r.getChildContext())if(!(a in t))throw Error(o(108,q(e)||"Unknown",a));return M({},n,r)}function Da(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Ta,La=ja.current,Ca(ja,e),Ca(Aa,Aa.current),!0}function Ma(e,t,n){var r=e.stateNode;if(!r)throw Error(o(169));n?(e=Ia(e,t,La),r.__reactInternalMemoizedMergedChildContext=e,Ea(Aa),Ea(ja),Ca(ja,e)):Ea(Aa),Ca(Aa,n)}var Fa=null,za=!1,Ba=!1;function $a(e){null===Fa?Fa=[e]:Fa.push(e)}function Ua(){if(!Ba&&null!==Fa){Ba=!0;var e=0,t=yt;try{var n=Fa;for(yt=1;e<n.length;e++){var r=n[e];do{r=r(!0)}while(null!==r)}Fa=null,za=!1}catch(a){throw null!==Fa&&(Fa=Fa.slice(e+1)),Ve(Je,Ua),a}finally{yt=t,Ba=!1}}return null}var qa=[],Ha=0,Za=null,Ga=0,Va=[],Wa=0,Qa=null,Ka=1,Ya="";function Xa(e,t){qa[Ha++]=Ga,qa[Ha++]=Za,Za=e,Ga=t}function Ja(e,t,n){Va[Wa++]=Ka,Va[Wa++]=Ya,Va[Wa++]=Qa,Qa=e;var r=Ka;e=Ya;var a=32-it(r)-1;r&=~(1<<a),n+=1;var o=32-it(t)+a;if(30<o){var i=a-a%5;o=(r&(1<<i)-1).toString(32),r>>=i,a-=i,Ka=1<<32-it(t)+a|n<<a|r,Ya=o+e}else Ka=1<<o|n<<a|r,Ya=e}function eo(e){null!==e.return&&(Xa(e,1),Ja(e,1,0))}function to(e){for(;e===Za;)Za=qa[--Ha],qa[Ha]=null,Ga=qa[--Ha],qa[Ha]=null;for(;e===Qa;)Qa=Va[--Wa],Va[Wa]=null,Ya=Va[--Wa],Va[Wa]=null,Ka=Va[--Wa],Va[Wa]=null}var no=null,ro=null,ao=!1,oo=null;function io(e,t){var n=Nc(5,null,null,0);n.elementType="DELETED",n.stateNode=t,n.return=e,null===(t=e.deletions)?(e.deletions=[n],e.flags|=16):t.push(n)}function so(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,no=e,ro=ca(t.firstChild),!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,no=e,ro=null,!0);case 13:return null!==(t=8!==t.nodeType?null:t)&&(n=null!==Qa?{id:Ka,overflow:Ya}:null,e.memoizedState={dehydrated:t,treeContext:n,retryLane:1073741824},(n=Nc(18,null,null,0)).stateNode=t,n.return=e,e.child=n,no=e,ro=null,!0);default:return!1}}function lo(e){return 0!=(1&e.mode)&&0==(128&e.flags)}function co(e){if(ao){var t=ro;if(t){var n=t;if(!so(e,t)){if(lo(e))throw Error(o(418));t=ca(n.nextSibling);var r=no;t&&so(e,t)?io(r,n):(e.flags=-4097&e.flags|2,ao=!1,no=e)}}else{if(lo(e))throw Error(o(418));e.flags=-4097&e.flags|2,ao=!1,no=e}}}function uo(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;no=e}function po(e){if(e!==no)return!1;if(!ao)return uo(e),ao=!0,!1;var t;if((t=3!==e.tag)&&!(t=5!==e.tag)&&(t="head"!==(t=e.type)&&"body"!==t&&!na(e.type,e.memoizedProps)),t&&(t=ro)){if(lo(e))throw fo(),Error(o(418));for(;t;)io(e,t),t=ca(t.nextSibling)}if(uo(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(o(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){ro=ca(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}ro=null}}else ro=no?ca(e.stateNode.nextSibling):null;return!0}function fo(){for(var e=ro;e;)e=ca(e.nextSibling)}function mo(){ro=no=null,ao=!1}function ho(e){null===oo?oo=[e]:oo.push(e)}var go=x.ReactCurrentBatchConfig;function bo(e,t){if(e&&e.defaultProps){for(var n in t=M({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}var vo=_a(null),yo=null,xo=null,wo=null;function ko(){wo=xo=yo=null}function So(e){var t=vo.current;Ea(vo),e._currentValue=t}function _o(e,t,n){for(;null!==e;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,null!==r&&(r.childLanes|=t)):null!==r&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Eo(e,t){yo=e,wo=xo=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(0!=(e.lanes&t)&&(xs=!0),e.firstContext=null)}function Co(e){var t=e._currentValue;if(wo!==e)if(e={context:e,memoizedValue:t,next:null},null===xo){if(null===yo)throw Error(o(308));xo=e,yo.dependencies={lanes:0,firstContext:e}}else xo=xo.next=e;return t}var To=null;function jo(e){null===To?To=[e]:To.push(e)}function Ao(e,t,n,r){var a=t.interleaved;return null===a?(n.next=n,jo(t)):(n.next=a.next,a.next=n),t.interleaved=n,Lo(e,r)}function Lo(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}var Ro=!1;function No(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Po(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Oo(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Io(e,t,n){var r=e.updateQueue;if(null===r)return null;if(r=r.shared,0!=(2&Al)){var a=r.pending;return null===a?t.next=t:(t.next=a.next,a.next=t),r.pending=t,Lo(e,n)}return null===(a=r.interleaved)?(t.next=t,jo(r)):(t.next=a.next,a.next=t),r.interleaved=t,Lo(e,n)}function Do(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,0!=(4194240&n))){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,vt(e,n)}}function Mo(e,t){var n=e.updateQueue,r=e.alternate;if(null!==r&&n===(r=r.updateQueue)){var a=null,o=null;if(null!==(n=n.firstBaseUpdate)){do{var i={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===o?a=o=i:o=o.next=i,n=n.next}while(null!==n);null===o?a=o=t:o=o.next=t}else a=o=t;return n={baseState:r.baseState,firstBaseUpdate:a,lastBaseUpdate:o,shared:r.shared,effects:r.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function Fo(e,t,n,r){var a=e.updateQueue;Ro=!1;var o=a.firstBaseUpdate,i=a.lastBaseUpdate,s=a.shared.pending;if(null!==s){a.shared.pending=null;var l=s,c=l.next;l.next=null,null===i?o=c:i.next=c,i=l;var u=e.alternate;null!==u&&((s=(u=u.updateQueue).lastBaseUpdate)!==i&&(null===s?u.firstBaseUpdate=c:s.next=c,u.lastBaseUpdate=l))}if(null!==o){var d=a.baseState;for(i=0,u=c=l=null,s=o;;){var p=s.lane,f=s.eventTime;if((r&p)===p){null!==u&&(u=u.next={eventTime:f,lane:0,tag:s.tag,payload:s.payload,callback:s.callback,next:null});e:{var m=e,h=s;switch(p=t,f=n,h.tag){case 1:if("function"==typeof(m=h.payload)){d=m.call(f,d,p);break e}d=m;break e;case 3:m.flags=-65537&m.flags|128;case 0:if(null==(p="function"==typeof(m=h.payload)?m.call(f,d,p):m))break e;d=M({},d,p);break e;case 2:Ro=!0}}null!==s.callback&&0!==s.lane&&(e.flags|=64,null===(p=a.effects)?a.effects=[s]:p.push(s))}else f={eventTime:f,lane:p,tag:s.tag,payload:s.payload,callback:s.callback,next:null},null===u?(c=u=f,l=d):u=u.next=f,i|=p;if(null===(s=s.next)){if(null===(s=a.shared.pending))break;s=(p=s).next,p.next=null,a.lastBaseUpdate=p,a.shared.pending=null}}if(null===u&&(l=d),a.baseState=l,a.firstBaseUpdate=c,a.lastBaseUpdate=u,null!==(t=a.shared.interleaved)){a=t;do{i|=a.lane,a=a.next}while(a!==t)}else null===o&&(a.shared.lanes=0);Ml|=i,e.lanes=i,e.memoizedState=d}}function zo(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t<e.length;t++){var r=e[t],a=r.callback;if(null!==a){if(r.callback=null,r=n,"function"!=typeof a)throw Error(o(191,a));a.call(r)}}}var Bo=(new r.Component).refs;function $o(e,t,n,r){n=null==(n=n(r,t=e.memoizedState))?t:M({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var Uo={isMounted:function(e){return!!(e=e._reactInternals)&&Ue(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var r=tc(),a=nc(e),o=Oo(r,a);o.payload=t,null!=n&&(o.callback=n),null!==(t=Io(e,o,a))&&(rc(t,e,a,r),Do(t,e,a))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var r=tc(),a=nc(e),o=Oo(r,a);o.tag=1,o.payload=t,null!=n&&(o.callback=n),null!==(t=Io(e,o,a))&&(rc(t,e,a,r),Do(t,e,a))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=tc(),r=nc(e),a=Oo(n,r);a.tag=2,null!=t&&(a.callback=t),null!==(t=Io(e,a,r))&&(rc(t,e,r,n),Do(t,e,r))}};function qo(e,t,n,r,a,o,i){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(r,o,i):!t.prototype||!t.prototype.isPureReactComponent||(!lr(n,r)||!lr(a,o))}function Ho(e,t,n){var r=!1,a=Ta,o=t.contextType;return"object"==typeof o&&null!==o?o=Co(o):(a=Na(t)?La:ja.current,o=(r=null!=(r=t.contextTypes))?Ra(e,a):Ta),t=new t(n,o),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=Uo,e.stateNode=t,t._reactInternals=e,r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=a,e.__reactInternalMemoizedMaskedChildContext=o),t}function Zo(e,t,n,r){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,r),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,r),t.state!==e&&Uo.enqueueReplaceState(t,t.state,null)}function Go(e,t,n,r){var a=e.stateNode;a.props=n,a.state=e.memoizedState,a.refs=Bo,No(e);var o=t.contextType;"object"==typeof o&&null!==o?a.context=Co(o):(o=Na(t)?La:ja.current,a.context=Ra(e,o)),a.state=e.memoizedState,"function"==typeof(o=t.getDerivedStateFromProps)&&($o(e,t,o,n),a.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof a.getSnapshotBeforeUpdate||"function"!=typeof a.UNSAFE_componentWillMount&&"function"!=typeof a.componentWillMount||(t=a.state,"function"==typeof a.componentWillMount&&a.componentWillMount(),"function"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount(),t!==a.state&&Uo.enqueueReplaceState(a,a.state,null),Fo(e,n,a,r),a.state=e.memoizedState),"function"==typeof a.componentDidMount&&(e.flags|=4194308)}function Vo(e,t,n){if(null!==(e=n.ref)&&"function"!=typeof e&&"object"!=typeof e){if(n._owner){if(n=n._owner){if(1!==n.tag)throw Error(o(309));var r=n.stateNode}if(!r)throw Error(o(147,e));var a=r,i=""+e;return null!==t&&null!==t.ref&&"function"==typeof t.ref&&t.ref._stringRef===i?t.ref:(t=function(e){var t=a.refs;t===Bo&&(t=a.refs={}),null===e?delete t[i]:t[i]=e},t._stringRef=i,t)}if("string"!=typeof e)throw Error(o(284));if(!n._owner)throw Error(o(290,e))}return e}function Wo(e,t){throw e=Object.prototype.toString.call(t),Error(o(31,"[object Object]"===e?"object with keys {"+Object.keys(t).join(", ")+"}":e))}function Qo(e){return(0,e._init)(e._payload)}function Ko(e){function t(t,n){if(e){var r=t.deletions;null===r?(t.deletions=[n],t.flags|=16):r.push(n)}}function n(n,r){if(!e)return null;for(;null!==r;)t(n,r),r=r.sibling;return null}function r(e,t){for(e=new Map;null!==t;)null!==t.key?e.set(t.key,t):e.set(t.index,t),t=t.sibling;return e}function a(e,t){return(e=Oc(e,t)).index=0,e.sibling=null,e}function i(t,n,r){return t.index=r,e?null!==(r=t.alternate)?(r=r.index)<n?(t.flags|=2,n):r:(t.flags|=2,n):(t.flags|=1048576,n)}function s(t){return e&&null===t.alternate&&(t.flags|=2),t}function l(e,t,n,r){return null===t||6!==t.tag?((t=Fc(n,e.mode,r)).return=e,t):((t=a(t,n)).return=e,t)}function c(e,t,n,r){var o=n.type;return o===S?d(e,t,n.props.children,r,n.key):null!==t&&(t.elementType===o||"object"==typeof o&&null!==o&&o.$$typeof===N&&Qo(o)===t.type)?((r=a(t,n.props)).ref=Vo(e,t,n),r.return=e,r):((r=Ic(n.type,n.key,n.props,null,e.mode,r)).ref=Vo(e,t,n),r.return=e,r)}function u(e,t,n,r){return null===t||4!==t.tag||t.stateNode.containerInfo!==n.containerInfo||t.stateNode.implementation!==n.implementation?((t=zc(n,e.mode,r)).return=e,t):((t=a(t,n.children||[])).return=e,t)}function d(e,t,n,r,o){return null===t||7!==t.tag?((t=Dc(n,e.mode,r,o)).return=e,t):((t=a(t,n)).return=e,t)}function p(e,t,n){if("string"==typeof t&&""!==t||"number"==typeof t)return(t=Fc(""+t,e.mode,n)).return=e,t;if("object"==typeof t&&null!==t){switch(t.$$typeof){case w:return(n=Ic(t.type,t.key,t.props,null,e.mode,n)).ref=Vo(e,null,t),n.return=e,n;case k:return(t=zc(t,e.mode,n)).return=e,t;case N:return p(e,(0,t._init)(t._payload),n)}if(te(t)||I(t))return(t=Dc(t,e.mode,n,null)).return=e,t;Wo(e,t)}return null}function f(e,t,n,r){var a=null!==t?t.key:null;if("string"==typeof n&&""!==n||"number"==typeof n)return null!==a?null:l(e,t,""+n,r);if("object"==typeof n&&null!==n){switch(n.$$typeof){case w:return n.key===a?c(e,t,n,r):null;case k:return n.key===a?u(e,t,n,r):null;case N:return f(e,t,(a=n._init)(n._payload),r)}if(te(n)||I(n))return null!==a?null:d(e,t,n,r,null);Wo(e,n)}return null}function m(e,t,n,r,a){if("string"==typeof r&&""!==r||"number"==typeof r)return l(t,e=e.get(n)||null,""+r,a);if("object"==typeof r&&null!==r){switch(r.$$typeof){case w:return c(t,e=e.get(null===r.key?n:r.key)||null,r,a);case k:return u(t,e=e.get(null===r.key?n:r.key)||null,r,a);case N:return m(e,t,n,(0,r._init)(r._payload),a)}if(te(r)||I(r))return d(t,e=e.get(n)||null,r,a,null);Wo(t,r)}return null}function h(a,o,s,l){for(var c=null,u=null,d=o,h=o=0,g=null;null!==d&&h<s.length;h++){d.index>h?(g=d,d=null):g=d.sibling;var b=f(a,d,s[h],l);if(null===b){null===d&&(d=g);break}e&&d&&null===b.alternate&&t(a,d),o=i(b,o,h),null===u?c=b:u.sibling=b,u=b,d=g}if(h===s.length)return n(a,d),ao&&Xa(a,h),c;if(null===d){for(;h<s.length;h++)null!==(d=p(a,s[h],l))&&(o=i(d,o,h),null===u?c=d:u.sibling=d,u=d);return ao&&Xa(a,h),c}for(d=r(a,d);h<s.length;h++)null!==(g=m(d,a,h,s[h],l))&&(e&&null!==g.alternate&&d.delete(null===g.key?h:g.key),o=i(g,o,h),null===u?c=g:u.sibling=g,u=g);return e&&d.forEach((function(e){return t(a,e)})),ao&&Xa(a,h),c}function g(a,s,l,c){var u=I(l);if("function"!=typeof u)throw Error(o(150));if(null==(l=u.call(l)))throw Error(o(151));for(var d=u=null,h=s,g=s=0,b=null,v=l.next();null!==h&&!v.done;g++,v=l.next()){h.index>g?(b=h,h=null):b=h.sibling;var y=f(a,h,v.value,c);if(null===y){null===h&&(h=b);break}e&&h&&null===y.alternate&&t(a,h),s=i(y,s,g),null===d?u=y:d.sibling=y,d=y,h=b}if(v.done)return n(a,h),ao&&Xa(a,g),u;if(null===h){for(;!v.done;g++,v=l.next())null!==(v=p(a,v.value,c))&&(s=i(v,s,g),null===d?u=v:d.sibling=v,d=v);return ao&&Xa(a,g),u}for(h=r(a,h);!v.done;g++,v=l.next())null!==(v=m(h,a,g,v.value,c))&&(e&&null!==v.alternate&&h.delete(null===v.key?g:v.key),s=i(v,s,g),null===d?u=v:d.sibling=v,d=v);return e&&h.forEach((function(e){return t(a,e)})),ao&&Xa(a,g),u}return function e(r,o,i,l){if("object"==typeof i&&null!==i&&i.type===S&&null===i.key&&(i=i.props.children),"object"==typeof i&&null!==i){switch(i.$$typeof){case w:e:{for(var c=i.key,u=o;null!==u;){if(u.key===c){if((c=i.type)===S){if(7===u.tag){n(r,u.sibling),(o=a(u,i.props.children)).return=r,r=o;break e}}else if(u.elementType===c||"object"==typeof c&&null!==c&&c.$$typeof===N&&Qo(c)===u.type){n(r,u.sibling),(o=a(u,i.props)).ref=Vo(r,u,i),o.return=r,r=o;break e}n(r,u);break}t(r,u),u=u.sibling}i.type===S?((o=Dc(i.props.children,r.mode,l,i.key)).return=r,r=o):((l=Ic(i.type,i.key,i.props,null,r.mode,l)).ref=Vo(r,o,i),l.return=r,r=l)}return s(r);case k:e:{for(u=i.key;null!==o;){if(o.key===u){if(4===o.tag&&o.stateNode.containerInfo===i.containerInfo&&o.stateNode.implementation===i.implementation){n(r,o.sibling),(o=a(o,i.children||[])).return=r,r=o;break e}n(r,o);break}t(r,o),o=o.sibling}(o=zc(i,r.mode,l)).return=r,r=o}return s(r);case N:return e(r,o,(u=i._init)(i._payload),l)}if(te(i))return h(r,o,i,l);if(I(i))return g(r,o,i,l);Wo(r,i)}return"string"==typeof i&&""!==i||"number"==typeof i?(i=""+i,null!==o&&6===o.tag?(n(r,o.sibling),(o=a(o,i)).return=r,r=o):(n(r,o),(o=Fc(i,r.mode,l)).return=r,r=o),s(r)):n(r,o)}}var Yo=Ko(!0),Xo=Ko(!1),Jo={},ei=_a(Jo),ti=_a(Jo),ni=_a(Jo);function ri(e){if(e===Jo)throw Error(o(174));return e}function ai(e,t){switch(Ca(ni,t),Ca(ti,e),Ca(ei,Jo),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:le(null,"");break;default:t=le(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}Ea(ei),Ca(ei,t)}function oi(){Ea(ei),Ea(ti),Ea(ni)}function ii(e){ri(ni.current);var t=ri(ei.current),n=le(t,e.type);t!==n&&(Ca(ti,e),Ca(ei,n))}function si(e){ti.current===e&&(Ea(ei),Ea(ti))}var li=_a(0);function ci(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(128&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var ui=[];function di(){for(var e=0;e<ui.length;e++)ui[e]._workInProgressVersionPrimary=null;ui.length=0}var pi=x.ReactCurrentDispatcher,fi=x.ReactCurrentBatchConfig,mi=0,hi=null,gi=null,bi=null,vi=!1,yi=!1,xi=0,wi=0;function ki(){throw Error(o(321))}function Si(e,t){if(null===t)return!1;for(var n=0;n<t.length&&n<e.length;n++)if(!sr(e[n],t[n]))return!1;return!0}function _i(e,t,n,r,a,i){if(mi=i,hi=t,t.memoizedState=null,t.updateQueue=null,t.lanes=0,pi.current=null===e||null===e.memoizedState?ss:ls,e=n(r,a),yi){i=0;do{if(yi=!1,xi=0,25<=i)throw Error(o(301));i+=1,bi=gi=null,t.updateQueue=null,pi.current=cs,e=n(r,a)}while(yi)}if(pi.current=is,t=null!==gi&&null!==gi.next,mi=0,bi=gi=hi=null,vi=!1,t)throw Error(o(300));return e}function Ei(){var e=0!==xi;return xi=0,e}function Ci(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===bi?hi.memoizedState=bi=e:bi=bi.next=e,bi}function Ti(){if(null===gi){var e=hi.alternate;e=null!==e?e.memoizedState:null}else e=gi.next;var t=null===bi?hi.memoizedState:bi.next;if(null!==t)bi=t,gi=e;else{if(null===e)throw Error(o(310));e={memoizedState:(gi=e).memoizedState,baseState:gi.baseState,baseQueue:gi.baseQueue,queue:gi.queue,next:null},null===bi?hi.memoizedState=bi=e:bi=bi.next=e}return bi}function ji(e,t){return"function"==typeof t?t(e):t}function Ai(e){var t=Ti(),n=t.queue;if(null===n)throw Error(o(311));n.lastRenderedReducer=e;var r=gi,a=r.baseQueue,i=n.pending;if(null!==i){if(null!==a){var s=a.next;a.next=i.next,i.next=s}r.baseQueue=a=i,n.pending=null}if(null!==a){i=a.next,r=r.baseState;var l=s=null,c=null,u=i;do{var d=u.lane;if((mi&d)===d)null!==c&&(c=c.next={lane:0,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null}),r=u.hasEagerState?u.eagerState:e(r,u.action);else{var p={lane:d,action:u.action,hasEagerState:u.hasEagerState,eagerState:u.eagerState,next:null};null===c?(l=c=p,s=r):c=c.next=p,hi.lanes|=d,Ml|=d}u=u.next}while(null!==u&&u!==i);null===c?s=r:c.next=l,sr(r,t.memoizedState)||(xs=!0),t.memoizedState=r,t.baseState=s,t.baseQueue=c,n.lastRenderedState=r}if(null!==(e=n.interleaved)){a=e;do{i=a.lane,hi.lanes|=i,Ml|=i,a=a.next}while(a!==e)}else null===a&&(n.lanes=0);return[t.memoizedState,n.dispatch]}function Li(e){var t=Ti(),n=t.queue;if(null===n)throw Error(o(311));n.lastRenderedReducer=e;var r=n.dispatch,a=n.pending,i=t.memoizedState;if(null!==a){n.pending=null;var s=a=a.next;do{i=e(i,s.action),s=s.next}while(s!==a);sr(i,t.memoizedState)||(xs=!0),t.memoizedState=i,null===t.baseQueue&&(t.baseState=i),n.lastRenderedState=i}return[i,r]}function Ri(){}function Ni(e,t){var n=hi,r=Ti(),a=t(),i=!sr(r.memoizedState,a);if(i&&(r.memoizedState=a,xs=!0),r=r.queue,Hi(Ii.bind(null,n,r,e),[e]),r.getSnapshot!==t||i||null!==bi&&1&bi.memoizedState.tag){if(n.flags|=2048,zi(9,Oi.bind(null,n,r,a,t),void 0,null),null===Ll)throw Error(o(349));0!=(30&mi)||Pi(n,t,a)}return a}function Pi(e,t,n){e.flags|=16384,e={getSnapshot:t,value:n},null===(t=hi.updateQueue)?(t={lastEffect:null,stores:null},hi.updateQueue=t,t.stores=[e]):null===(n=t.stores)?t.stores=[e]:n.push(e)}function Oi(e,t,n,r){t.value=n,t.getSnapshot=r,Di(t)&&Mi(e)}function Ii(e,t,n){return n((function(){Di(t)&&Mi(e)}))}function Di(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!sr(e,n)}catch(r){return!0}}function Mi(e){var t=Lo(e,1);null!==t&&rc(t,e,1,-1)}function Fi(e){var t=Ci();return"function"==typeof e&&(e=e()),t.memoizedState=t.baseState=e,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:ji,lastRenderedState:e},t.queue=e,e=e.dispatch=ns.bind(null,hi,e),[t.memoizedState,e]}function zi(e,t,n,r){return e={tag:e,create:t,destroy:n,deps:r,next:null},null===(t=hi.updateQueue)?(t={lastEffect:null,stores:null},hi.updateQueue=t,t.lastEffect=e.next=e):null===(n=t.lastEffect)?t.lastEffect=e.next=e:(r=n.next,n.next=e,e.next=r,t.lastEffect=e),e}function Bi(){return Ti().memoizedState}function $i(e,t,n,r){var a=Ci();hi.flags|=e,a.memoizedState=zi(1|t,n,void 0,void 0===r?null:r)}function Ui(e,t,n,r){var a=Ti();r=void 0===r?null:r;var o=void 0;if(null!==gi){var i=gi.memoizedState;if(o=i.destroy,null!==r&&Si(r,i.deps))return void(a.memoizedState=zi(t,n,o,r))}hi.flags|=e,a.memoizedState=zi(1|t,n,o,r)}function qi(e,t){return $i(8390656,8,e,t)}function Hi(e,t){return Ui(2048,8,e,t)}function Zi(e,t){return Ui(4,2,e,t)}function Gi(e,t){return Ui(4,4,e,t)}function Vi(e,t){return"function"==typeof t?(e=e(),t(e),function(){t(null)}):null!=t?(e=e(),t.current=e,function(){t.current=null}):void 0}function Wi(e,t,n){return n=null!=n?n.concat([e]):null,Ui(4,4,Vi.bind(null,t,e),n)}function Qi(){}function Ki(e,t){var n=Ti();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&Si(t,r[1])?r[0]:(n.memoizedState=[e,t],e)}function Yi(e,t){var n=Ti();t=void 0===t?null:t;var r=n.memoizedState;return null!==r&&null!==t&&Si(t,r[1])?r[0]:(e=e(),n.memoizedState=[e,t],e)}function Xi(e,t,n){return 0==(21&mi)?(e.baseState&&(e.baseState=!1,xs=!0),e.memoizedState=n):(sr(n,t)||(n=ht(),hi.lanes|=n,Ml|=n,e.baseState=!0),t)}function Ji(e,t){var n=yt;yt=0!==n&&4>n?n:4,e(!0);var r=fi.transition;fi.transition={};try{e(!1),t()}finally{yt=n,fi.transition=r}}function es(){return Ti().memoizedState}function ts(e,t,n){var r=nc(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},rs(e))as(t,n);else if(null!==(n=Ao(e,t,n,r))){rc(n,e,r,tc()),os(n,t,r)}}function ns(e,t,n){var r=nc(e),a={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(rs(e))as(t,a);else{var o=e.alternate;if(0===e.lanes&&(null===o||0===o.lanes)&&null!==(o=t.lastRenderedReducer))try{var i=t.lastRenderedState,s=o(i,n);if(a.hasEagerState=!0,a.eagerState=s,sr(s,i)){var l=t.interleaved;return null===l?(a.next=a,jo(t)):(a.next=l.next,l.next=a),void(t.interleaved=a)}}catch(c){}null!==(n=Ao(e,t,a,r))&&(rc(n,e,r,a=tc()),os(n,t,r))}}function rs(e){var t=e.alternate;return e===hi||null!==t&&t===hi}function as(e,t){yi=vi=!0;var n=e.pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function os(e,t,n){if(0!=(4194240&n)){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,vt(e,n)}}var is={readContext:Co,useCallback:ki,useContext:ki,useEffect:ki,useImperativeHandle:ki,useInsertionEffect:ki,useLayoutEffect:ki,useMemo:ki,useReducer:ki,useRef:ki,useState:ki,useDebugValue:ki,useDeferredValue:ki,useTransition:ki,useMutableSource:ki,useSyncExternalStore:ki,useId:ki,unstable_isNewReconciler:!1},ss={readContext:Co,useCallback:function(e,t){return Ci().memoizedState=[e,void 0===t?null:t],e},useContext:Co,useEffect:qi,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,$i(4194308,4,Vi.bind(null,t,e),n)},useLayoutEffect:function(e,t){return $i(4194308,4,e,t)},useInsertionEffect:function(e,t){return $i(4,2,e,t)},useMemo:function(e,t){var n=Ci();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Ci();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=ts.bind(null,hi,e),[r.memoizedState,e]},useRef:function(e){return e={current:e},Ci().memoizedState=e},useState:Fi,useDebugValue:Qi,useDeferredValue:function(e){return Ci().memoizedState=e},useTransition:function(){var e=Fi(!1),t=e[0];return e=Ji.bind(null,e[1]),Ci().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=hi,a=Ci();if(ao){if(void 0===n)throw Error(o(407));n=n()}else{if(n=t(),null===Ll)throw Error(o(349));0!=(30&mi)||Pi(r,t,n)}a.memoizedState=n;var i={value:n,getSnapshot:t};return a.queue=i,qi(Ii.bind(null,r,i,e),[e]),r.flags|=2048,zi(9,Oi.bind(null,r,i,n,t),void 0,null),n},useId:function(){var e=Ci(),t=Ll.identifierPrefix;if(ao){var n=Ya;t=":"+t+"R"+(n=(Ka&~(1<<32-it(Ka)-1)).toString(32)+n),0<(n=xi++)&&(t+="H"+n.toString(32)),t+=":"}else t=":"+t+"r"+(n=wi++).toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},ls={readContext:Co,useCallback:Ki,useContext:Co,useEffect:Hi,useImperativeHandle:Wi,useInsertionEffect:Zi,useLayoutEffect:Gi,useMemo:Yi,useReducer:Ai,useRef:Bi,useState:function(){return Ai(ji)},useDebugValue:Qi,useDeferredValue:function(e){return Xi(Ti(),gi.memoizedState,e)},useTransition:function(){return[Ai(ji)[0],Ti().memoizedState]},useMutableSource:Ri,useSyncExternalStore:Ni,useId:es,unstable_isNewReconciler:!1},cs={readContext:Co,useCallback:Ki,useContext:Co,useEffect:Hi,useImperativeHandle:Wi,useInsertionEffect:Zi,useLayoutEffect:Gi,useMemo:Yi,useReducer:Li,useRef:Bi,useState:function(){return Li(ji)},useDebugValue:Qi,useDeferredValue:function(e){var t=Ti();return null===gi?t.memoizedState=e:Xi(t,gi.memoizedState,e)},useTransition:function(){return[Li(ji)[0],Ti().memoizedState]},useMutableSource:Ri,useSyncExternalStore:Ni,useId:es,unstable_isNewReconciler:!1};function us(e,t){try{var n="",r=t;do{n+=$(r),r=r.return}while(r);var a=n}catch(o){a="\nError generating stack: "+o.message+"\n"+o.stack}return{value:e,source:t,stack:a,digest:null}}function ds(e,t,n){return{value:e,source:null,stack:null!=n?n:null,digest:null!=t?t:null}}function ps(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}var fs="function"==typeof WeakMap?WeakMap:Map;function ms(e,t,n){(n=Oo(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){Zl||(Zl=!0,Gl=r),ps(0,t)},n}function hs(e,t,n){(n=Oo(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var a=t.value;n.payload=function(){return r(a)},n.callback=function(){ps(0,t)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){ps(0,t),"function"!=typeof r&&(null===Vl?Vl=new Set([this]):Vl.add(this));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}function gs(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new fs;var a=new Set;r.set(t,a)}else void 0===(a=r.get(t))&&(a=new Set,r.set(t,a));a.has(n)||(a.add(n),e=Cc.bind(null,e,t,n),t.then(e,e))}function bs(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)||null!==t.dehydrated),t)return e;e=e.return}while(null!==e);return null}function vs(e,t,n,r,a){return 0==(1&e.mode)?(e===t?e.flags|=65536:(e.flags|=128,n.flags|=131072,n.flags&=-52805,1===n.tag&&(null===n.alternate?n.tag=17:((t=Oo(-1,1)).tag=2,Io(n,t,1))),n.lanes|=1),e):(e.flags|=65536,e.lanes=a,e)}var ys=x.ReactCurrentOwner,xs=!1;function ws(e,t,n,r){t.child=null===e?Xo(t,null,n,r):Yo(t,e.child,n,r)}function ks(e,t,n,r,a){n=n.render;var o=t.ref;return Eo(t,a),r=_i(e,t,n,r,o,a),n=Ei(),null===e||xs?(ao&&n&&eo(t),t.flags|=1,ws(e,t,r,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~a,Zs(e,t,a))}function Ss(e,t,n,r,a){if(null===e){var o=n.type;return"function"!=typeof o||Pc(o)||void 0!==o.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Ic(n.type,null,r,t,t.mode,a)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=o,_s(e,t,o,r,a))}if(o=e.child,0==(e.lanes&a)){var i=o.memoizedProps;if((n=null!==(n=n.compare)?n:lr)(i,r)&&e.ref===t.ref)return Zs(e,t,a)}return t.flags|=1,(e=Oc(o,r)).ref=t.ref,e.return=t,t.child=e}function _s(e,t,n,r,a){if(null!==e){var o=e.memoizedProps;if(lr(o,r)&&e.ref===t.ref){if(xs=!1,t.pendingProps=r=o,0==(e.lanes&a))return t.lanes=e.lanes,Zs(e,t,a);0!=(131072&e.flags)&&(xs=!0)}}return Ts(e,t,n,r,a)}function Es(e,t,n){var r=t.pendingProps,a=r.children,o=null!==e?e.memoizedState:null;if("hidden"===r.mode)if(0==(1&t.mode))t.memoizedState={baseLanes:0,cachePool:null,transitions:null},Ca(Ol,Pl),Pl|=n;else{if(0==(1073741824&n))return e=null!==o?o.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,Ca(Ol,Pl),Pl|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=null!==o?o.baseLanes:n,Ca(Ol,Pl),Pl|=r}else null!==o?(r=o.baseLanes|n,t.memoizedState=null):r=n,Ca(Ol,Pl),Pl|=r;return ws(e,t,a,n),t.child}function Cs(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=512,t.flags|=2097152)}function Ts(e,t,n,r,a){var o=Na(n)?La:ja.current;return o=Ra(t,o),Eo(t,a),n=_i(e,t,n,r,o,a),r=Ei(),null===e||xs?(ao&&r&&eo(t),t.flags|=1,ws(e,t,n,a),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~a,Zs(e,t,a))}function js(e,t,n,r,a){if(Na(n)){var o=!0;Da(t)}else o=!1;if(Eo(t,a),null===t.stateNode)Hs(e,t),Ho(t,n,r),Go(t,n,r,a),r=!0;else if(null===e){var i=t.stateNode,s=t.memoizedProps;i.props=s;var l=i.context,c=n.contextType;"object"==typeof c&&null!==c?c=Co(c):c=Ra(t,c=Na(n)?La:ja.current);var u=n.getDerivedStateFromProps,d="function"==typeof u||"function"==typeof i.getSnapshotBeforeUpdate;d||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(s!==r||l!==c)&&Zo(t,i,r,c),Ro=!1;var p=t.memoizedState;i.state=p,Fo(t,r,i,a),l=t.memoizedState,s!==r||p!==l||Aa.current||Ro?("function"==typeof u&&($o(t,n,u,r),l=t.memoizedState),(s=Ro||qo(t,n,s,r,p,l,c))?(d||"function"!=typeof i.UNSAFE_componentWillMount&&"function"!=typeof i.componentWillMount||("function"==typeof i.componentWillMount&&i.componentWillMount(),"function"==typeof i.UNSAFE_componentWillMount&&i.UNSAFE_componentWillMount()),"function"==typeof i.componentDidMount&&(t.flags|=4194308)):("function"==typeof i.componentDidMount&&(t.flags|=4194308),t.memoizedProps=r,t.memoizedState=l),i.props=r,i.state=l,i.context=c,r=s):("function"==typeof i.componentDidMount&&(t.flags|=4194308),r=!1)}else{i=t.stateNode,Po(e,t),s=t.memoizedProps,c=t.type===t.elementType?s:bo(t.type,s),i.props=c,d=t.pendingProps,p=i.context,"object"==typeof(l=n.contextType)&&null!==l?l=Co(l):l=Ra(t,l=Na(n)?La:ja.current);var f=n.getDerivedStateFromProps;(u="function"==typeof f||"function"==typeof i.getSnapshotBeforeUpdate)||"function"!=typeof i.UNSAFE_componentWillReceiveProps&&"function"!=typeof i.componentWillReceiveProps||(s!==d||p!==l)&&Zo(t,i,r,l),Ro=!1,p=t.memoizedState,i.state=p,Fo(t,r,i,a);var m=t.memoizedState;s!==d||p!==m||Aa.current||Ro?("function"==typeof f&&($o(t,n,f,r),m=t.memoizedState),(c=Ro||qo(t,n,c,r,p,m,l)||!1)?(u||"function"!=typeof i.UNSAFE_componentWillUpdate&&"function"!=typeof i.componentWillUpdate||("function"==typeof i.componentWillUpdate&&i.componentWillUpdate(r,m,l),"function"==typeof i.UNSAFE_componentWillUpdate&&i.UNSAFE_componentWillUpdate(r,m,l)),"function"==typeof i.componentDidUpdate&&(t.flags|=4),"function"==typeof i.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!=typeof i.componentDidUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),t.memoizedProps=r,t.memoizedState=m),i.props=r,i.state=m,i.context=l,r=c):("function"!=typeof i.componentDidUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof i.getSnapshotBeforeUpdate||s===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),r=!1)}return As(e,t,n,r,o,a)}function As(e,t,n,r,a,o){Cs(e,t);var i=0!=(128&t.flags);if(!r&&!i)return a&&Ma(t,n,!1),Zs(e,t,o);r=t.stateNode,ys.current=t;var s=i&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&i?(t.child=Yo(t,e.child,null,o),t.child=Yo(t,null,s,o)):ws(e,t,s,o),t.memoizedState=r.state,a&&Ma(t,n,!0),t.child}function Ls(e){var t=e.stateNode;t.pendingContext?Oa(0,t.pendingContext,t.pendingContext!==t.context):t.context&&Oa(0,t.context,!1),ai(e,t.containerInfo)}function Rs(e,t,n,r,a){return mo(),ho(a),t.flags|=256,ws(e,t,n,r),t.child}var Ns,Ps,Os,Is,Ds={dehydrated:null,treeContext:null,retryLane:0};function Ms(e){return{baseLanes:e,cachePool:null,transitions:null}}function Fs(e,t,n){var r,a=t.pendingProps,i=li.current,s=!1,l=0!=(128&t.flags);if((r=l)||(r=(null===e||null!==e.memoizedState)&&0!=(2&i)),r?(s=!0,t.flags&=-129):null!==e&&null===e.memoizedState||(i|=1),Ca(li,1&i),null===e)return co(t),null!==(e=t.memoizedState)&&null!==(e=e.dehydrated)?(0==(1&t.mode)?t.lanes=1:"$!"===e.data?t.lanes=8:t.lanes=1073741824,null):(l=a.children,e=a.fallback,s?(a=t.mode,s=t.child,l={mode:"hidden",children:l},0==(1&a)&&null!==s?(s.childLanes=0,s.pendingProps=l):s=Mc(l,a,0,null),e=Dc(e,a,n,null),s.return=t,e.return=t,s.sibling=e,t.child=s,t.child.memoizedState=Ms(n),t.memoizedState=Ds,e):zs(t,l));if(null!==(i=e.memoizedState)&&null!==(r=i.dehydrated))return function(e,t,n,r,a,i,s){if(n)return 256&t.flags?(t.flags&=-257,Bs(e,t,s,r=ds(Error(o(422))))):null!==t.memoizedState?(t.child=e.child,t.flags|=128,null):(i=r.fallback,a=t.mode,r=Mc({mode:"visible",children:r.children},a,0,null),(i=Dc(i,a,s,null)).flags|=2,r.return=t,i.return=t,r.sibling=i,t.child=r,0!=(1&t.mode)&&Yo(t,e.child,null,s),t.child.memoizedState=Ms(s),t.memoizedState=Ds,i);if(0==(1&t.mode))return Bs(e,t,s,null);if("$!"===a.data){if(r=a.nextSibling&&a.nextSibling.dataset)var l=r.dgst;return r=l,Bs(e,t,s,r=ds(i=Error(o(419)),r,void 0))}if(l=0!=(s&e.childLanes),xs||l){if(null!==(r=Ll)){switch(s&-s){case 4:a=2;break;case 16:a=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:a=32;break;case 536870912:a=268435456;break;default:a=0}0!==(a=0!=(a&(r.suspendedLanes|s))?0:a)&&a!==i.retryLane&&(i.retryLane=a,Lo(e,a),rc(r,e,a,-1))}return gc(),Bs(e,t,s,r=ds(Error(o(421))))}return"$?"===a.data?(t.flags|=128,t.child=e.child,t=jc.bind(null,e),a._reactRetry=t,null):(e=i.treeContext,ro=ca(a.nextSibling),no=t,ao=!0,oo=null,null!==e&&(Va[Wa++]=Ka,Va[Wa++]=Ya,Va[Wa++]=Qa,Ka=e.id,Ya=e.overflow,Qa=t),t=zs(t,r.children),t.flags|=4096,t)}(e,t,l,a,r,i,n);if(s){s=a.fallback,l=t.mode,r=(i=e.child).sibling;var c={mode:"hidden",children:a.children};return 0==(1&l)&&t.child!==i?((a=t.child).childLanes=0,a.pendingProps=c,t.deletions=null):(a=Oc(i,c)).subtreeFlags=14680064&i.subtreeFlags,null!==r?s=Oc(r,s):(s=Dc(s,l,n,null)).flags|=2,s.return=t,a.return=t,a.sibling=s,t.child=a,a=s,s=t.child,l=null===(l=e.child.memoizedState)?Ms(n):{baseLanes:l.baseLanes|n,cachePool:null,transitions:l.transitions},s.memoizedState=l,s.childLanes=e.childLanes&~n,t.memoizedState=Ds,a}return e=(s=e.child).sibling,a=Oc(s,{mode:"visible",children:a.children}),0==(1&t.mode)&&(a.lanes=n),a.return=t,a.sibling=null,null!==e&&(null===(n=t.deletions)?(t.deletions=[e],t.flags|=16):n.push(e)),t.child=a,t.memoizedState=null,a}function zs(e,t){return(t=Mc({mode:"visible",children:t},e.mode,0,null)).return=e,e.child=t}function Bs(e,t,n,r){return null!==r&&ho(r),Yo(t,e.child,null,n),(e=zs(t,t.pendingProps.children)).flags|=2,t.memoizedState=null,e}function $s(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),_o(e.return,t,n)}function Us(e,t,n,r,a){var o=e.memoizedState;null===o?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:a}:(o.isBackwards=t,o.rendering=null,o.renderingStartTime=0,o.last=r,o.tail=n,o.tailMode=a)}function qs(e,t,n){var r=t.pendingProps,a=r.revealOrder,o=r.tail;if(ws(e,t,r.children,n),0!=(2&(r=li.current)))r=1&r|2,t.flags|=128;else{if(null!==e&&0!=(128&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&$s(e,n,t);else if(19===e.tag)$s(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(Ca(li,r),0==(1&t.mode))t.memoizedState=null;else switch(a){case"forwards":for(n=t.child,a=null;null!==n;)null!==(e=n.alternate)&&null===ci(e)&&(a=n),n=n.sibling;null===(n=a)?(a=t.child,t.child=null):(a=n.sibling,n.sibling=null),Us(t,!1,a,n,o);break;case"backwards":for(n=null,a=t.child,t.child=null;null!==a;){if(null!==(e=a.alternate)&&null===ci(e)){t.child=a;break}e=a.sibling,a.sibling=n,n=a,a=e}Us(t,!0,n,null,o);break;case"together":Us(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function Hs(e,t){0==(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2)}function Zs(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Ml|=t.lanes,0==(n&t.childLanes))return null;if(null!==e&&t.child!==e.child)throw Error(o(153));if(null!==t.child){for(n=Oc(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Oc(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function Gs(e,t){if(!ao)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function Vs(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,r=0;if(t)for(var a=e.child;null!==a;)n|=a.lanes|a.childLanes,r|=14680064&a.subtreeFlags,r|=14680064&a.flags,a.return=e,a=a.sibling;else for(a=e.child;null!==a;)n|=a.lanes|a.childLanes,r|=a.subtreeFlags,r|=a.flags,a.return=e,a=a.sibling;return e.subtreeFlags|=r,e.childLanes=n,t}function Ws(e,t,n){var r=t.pendingProps;switch(to(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Vs(t),null;case 1:case 17:return Na(t.type)&&Pa(),Vs(t),null;case 3:return r=t.stateNode,oi(),Ea(Aa),Ea(ja),di(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),null!==e&&null!==e.child||(po(t)?t.flags|=4:null===e||e.memoizedState.isDehydrated&&0==(256&t.flags)||(t.flags|=1024,null!==oo&&(sc(oo),oo=null))),Ps(e,t),Vs(t),null;case 5:si(t);var a=ri(ni.current);if(n=t.type,null!==e&&null!=t.stateNode)Os(e,t,n,r,a),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!r){if(null===t.stateNode)throw Error(o(166));return Vs(t),null}if(e=ri(ei.current),po(t)){r=t.stateNode,n=t.type;var i=t.memoizedProps;switch(r[pa]=t,r[fa]=i,e=0!=(1&t.mode),n){case"dialog":zr("cancel",r),zr("close",r);break;case"iframe":case"object":case"embed":zr("load",r);break;case"video":case"audio":for(a=0;a<Ir.length;a++)zr(Ir[a],r);break;case"source":zr("error",r);break;case"img":case"image":case"link":zr("error",r),zr("load",r);break;case"details":zr("toggle",r);break;case"input":K(r,i),zr("invalid",r);break;case"select":r._wrapperState={wasMultiple:!!i.multiple},zr("invalid",r);break;case"textarea":ae(r,i),zr("invalid",r)}for(var l in ve(n,i),a=null,i)if(i.hasOwnProperty(l)){var c=i[l];"children"===l?"string"==typeof c?r.textContent!==c&&(!0!==i.suppressHydrationWarning&&Xr(r.textContent,c,e),a=["children",c]):"number"==typeof c&&r.textContent!==""+c&&(!0!==i.suppressHydrationWarning&&Xr(r.textContent,c,e),a=["children",""+c]):s.hasOwnProperty(l)&&null!=c&&"onScroll"===l&&zr("scroll",r)}switch(n){case"input":G(r),J(r,i,!0);break;case"textarea":G(r),ie(r);break;case"select":case"option":break;default:"function"==typeof i.onClick&&(r.onclick=Jr)}r=a,t.updateQueue=r,null!==r&&(t.flags|=4)}else{l=9===a.nodeType?a:a.ownerDocument,"http://www.w3.org/1999/xhtml"===e&&(e=se(n)),"http://www.w3.org/1999/xhtml"===e?"script"===n?((e=l.createElement("div")).innerHTML="<script><\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=l.createElement(n,{is:r.is}):(e=l.createElement(n),"select"===n&&(l=e,r.multiple?l.multiple=!0:r.size&&(l.size=r.size))):e=l.createElementNS(e,n),e[pa]=t,e[fa]=r,Ns(e,t,!1,!1),t.stateNode=e;e:{switch(l=ye(n,r),n){case"dialog":zr("cancel",e),zr("close",e),a=r;break;case"iframe":case"object":case"embed":zr("load",e),a=r;break;case"video":case"audio":for(a=0;a<Ir.length;a++)zr(Ir[a],e);a=r;break;case"source":zr("error",e),a=r;break;case"img":case"image":case"link":zr("error",e),zr("load",e),a=r;break;case"details":zr("toggle",e),a=r;break;case"input":K(e,r),a=Q(e,r),zr("invalid",e);break;case"option":default:a=r;break;case"select":e._wrapperState={wasMultiple:!!r.multiple},a=M({},r,{value:void 0}),zr("invalid",e);break;case"textarea":ae(e,r),a=re(e,r),zr("invalid",e)}for(i in ve(n,a),c=a)if(c.hasOwnProperty(i)){var u=c[i];"style"===i?ge(e,u):"dangerouslySetInnerHTML"===i?null!=(u=u?u.__html:void 0)&&de(e,u):"children"===i?"string"==typeof u?("textarea"!==n||""!==u)&&pe(e,u):"number"==typeof u&&pe(e,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(s.hasOwnProperty(i)?null!=u&&"onScroll"===i&&zr("scroll",e):null!=u&&y(e,i,u,l))}switch(n){case"input":G(e),J(e,r,!1);break;case"textarea":G(e),ie(e);break;case"option":null!=r.value&&e.setAttribute("value",""+H(r.value));break;case"select":e.multiple=!!r.multiple,null!=(i=r.value)?ne(e,!!r.multiple,i,!1):null!=r.defaultValue&&ne(e,!!r.multiple,r.defaultValue,!0);break;default:"function"==typeof a.onClick&&(e.onclick=Jr)}switch(n){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break e;case"img":r=!0;break e;default:r=!1}}r&&(t.flags|=4)}null!==t.ref&&(t.flags|=512,t.flags|=2097152)}return Vs(t),null;case 6:if(e&&null!=t.stateNode)Is(e,t,e.memoizedProps,r);else{if("string"!=typeof r&&null===t.stateNode)throw Error(o(166));if(n=ri(ni.current),ri(ei.current),po(t)){if(r=t.stateNode,n=t.memoizedProps,r[pa]=t,(i=r.nodeValue!==n)&&null!==(e=no))switch(e.tag){case 3:Xr(r.nodeValue,n,0!=(1&e.mode));break;case 5:!0!==e.memoizedProps.suppressHydrationWarning&&Xr(r.nodeValue,n,0!=(1&e.mode))}i&&(t.flags|=4)}else(r=(9===n.nodeType?n:n.ownerDocument).createTextNode(r))[pa]=t,t.stateNode=r}return Vs(t),null;case 13:if(Ea(li),r=t.memoizedState,null===e||null!==e.memoizedState&&null!==e.memoizedState.dehydrated){if(ao&&null!==ro&&0!=(1&t.mode)&&0==(128&t.flags))fo(),mo(),t.flags|=98560,i=!1;else if(i=po(t),null!==r&&null!==r.dehydrated){if(null===e){if(!i)throw Error(o(318));if(!(i=null!==(i=t.memoizedState)?i.dehydrated:null))throw Error(o(317));i[pa]=t}else mo(),0==(128&t.flags)&&(t.memoizedState=null),t.flags|=4;Vs(t),i=!1}else null!==oo&&(sc(oo),oo=null),i=!0;if(!i)return 65536&t.flags?t:null}return 0!=(128&t.flags)?(t.lanes=n,t):((r=null!==r)!==(null!==e&&null!==e.memoizedState)&&r&&(t.child.flags|=8192,0!=(1&t.mode)&&(null===e||0!=(1&li.current)?0===Il&&(Il=3):gc())),null!==t.updateQueue&&(t.flags|=4),Vs(t),null);case 4:return oi(),Ps(e,t),null===e&&Ur(t.stateNode.containerInfo),Vs(t),null;case 10:return So(t.type._context),Vs(t),null;case 19:if(Ea(li),null===(i=t.memoizedState))return Vs(t),null;if(r=0!=(128&t.flags),null===(l=i.rendering))if(r)Gs(i,!1);else{if(0!==Il||null!==e&&0!=(128&e.flags))for(e=t.child;null!==e;){if(null!==(l=ci(e))){for(t.flags|=128,Gs(i,!1),null!==(r=l.updateQueue)&&(t.updateQueue=r,t.flags|=4),t.subtreeFlags=0,r=n,n=t.child;null!==n;)e=r,(i=n).flags&=14680066,null===(l=i.alternate)?(i.childLanes=0,i.lanes=e,i.child=null,i.subtreeFlags=0,i.memoizedProps=null,i.memoizedState=null,i.updateQueue=null,i.dependencies=null,i.stateNode=null):(i.childLanes=l.childLanes,i.lanes=l.lanes,i.child=l.child,i.subtreeFlags=0,i.deletions=null,i.memoizedProps=l.memoizedProps,i.memoizedState=l.memoizedState,i.updateQueue=l.updateQueue,i.type=l.type,e=l.dependencies,i.dependencies=null===e?null:{lanes:e.lanes,firstContext:e.firstContext}),n=n.sibling;return Ca(li,1&li.current|2),t.child}e=e.sibling}null!==i.tail&&Ye()>ql&&(t.flags|=128,r=!0,Gs(i,!1),t.lanes=4194304)}else{if(!r)if(null!==(e=ci(l))){if(t.flags|=128,r=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),Gs(i,!0),null===i.tail&&"hidden"===i.tailMode&&!l.alternate&&!ao)return Vs(t),null}else 2*Ye()-i.renderingStartTime>ql&&1073741824!==n&&(t.flags|=128,r=!0,Gs(i,!1),t.lanes=4194304);i.isBackwards?(l.sibling=t.child,t.child=l):(null!==(n=i.last)?n.sibling=l:t.child=l,i.last=l)}return null!==i.tail?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=Ye(),t.sibling=null,n=li.current,Ca(li,r?1&n|2:1&n),t):(Vs(t),null);case 22:case 23:return pc(),r=null!==t.memoizedState,null!==e&&null!==e.memoizedState!==r&&(t.flags|=8192),r&&0!=(1&t.mode)?0!=(1073741824&Pl)&&(Vs(t),6&t.subtreeFlags&&(t.flags|=8192)):Vs(t),null;case 24:case 25:return null}throw Error(o(156,t.tag))}function Qs(e,t){switch(to(t),t.tag){case 1:return Na(t.type)&&Pa(),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return oi(),Ea(Aa),Ea(ja),di(),0!=(65536&(e=t.flags))&&0==(128&e)?(t.flags=-65537&e|128,t):null;case 5:return si(t),null;case 13:if(Ea(li),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(o(340));mo()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return Ea(li),null;case 4:return oi(),null;case 10:return So(t.type._context),null;case 22:case 23:return pc(),null;default:return null}}Ns=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Ps=function(){},Os=function(e,t,n,r){var a=e.memoizedProps;if(a!==r){e=t.stateNode,ri(ei.current);var o,i=null;switch(n){case"input":a=Q(e,a),r=Q(e,r),i=[];break;case"select":a=M({},a,{value:void 0}),r=M({},r,{value:void 0}),i=[];break;case"textarea":a=re(e,a),r=re(e,r),i=[];break;default:"function"!=typeof a.onClick&&"function"==typeof r.onClick&&(e.onclick=Jr)}for(u in ve(n,r),n=null,a)if(!r.hasOwnProperty(u)&&a.hasOwnProperty(u)&&null!=a[u])if("style"===u){var l=a[u];for(o in l)l.hasOwnProperty(o)&&(n||(n={}),n[o]="")}else"dangerouslySetInnerHTML"!==u&&"children"!==u&&"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&"autoFocus"!==u&&(s.hasOwnProperty(u)?i||(i=[]):(i=i||[]).push(u,null));for(u in r){var c=r[u];if(l=null!=a?a[u]:void 0,r.hasOwnProperty(u)&&c!==l&&(null!=c||null!=l))if("style"===u)if(l){for(o in l)!l.hasOwnProperty(o)||c&&c.hasOwnProperty(o)||(n||(n={}),n[o]="");for(o in c)c.hasOwnProperty(o)&&l[o]!==c[o]&&(n||(n={}),n[o]=c[o])}else n||(i||(i=[]),i.push(u,n)),n=c;else"dangerouslySetInnerHTML"===u?(c=c?c.__html:void 0,l=l?l.__html:void 0,null!=c&&l!==c&&(i=i||[]).push(u,c)):"children"===u?"string"!=typeof c&&"number"!=typeof c||(i=i||[]).push(u,""+c):"suppressContentEditableWarning"!==u&&"suppressHydrationWarning"!==u&&(s.hasOwnProperty(u)?(null!=c&&"onScroll"===u&&zr("scroll",e),i||l===c||(i=[])):(i=i||[]).push(u,c))}n&&(i=i||[]).push("style",n);var u=i;(t.updateQueue=u)&&(t.flags|=4)}},Is=function(e,t,n,r){n!==r&&(t.flags|=4)};var Ks=!1,Ys=!1,Xs="function"==typeof WeakSet?WeakSet:Set,Js=null;function el(e,t){var n=e.ref;if(null!==n)if("function"==typeof n)try{n(null)}catch(r){Ec(e,t,r)}else n.current=null}function tl(e,t,n){try{n()}catch(r){Ec(e,t,r)}}var nl=!1;function rl(e,t,n){var r=t.updateQueue;if(null!==(r=null!==r?r.lastEffect:null)){var a=r=r.next;do{if((a.tag&e)===e){var o=a.destroy;a.destroy=void 0,void 0!==o&&tl(t,n,o)}a=a.next}while(a!==r)}}function al(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null)){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function ol(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag,e=n,"function"==typeof t?t(e):t.current=e}}function il(e){var t=e.alternate;null!==t&&(e.alternate=null,il(t)),e.child=null,e.deletions=null,e.sibling=null,5===e.tag&&(null!==(t=e.stateNode)&&(delete t[pa],delete t[fa],delete t[ha],delete t[ga],delete t[ba])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function sl(e){return 5===e.tag||3===e.tag||4===e.tag}function ll(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||sl(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}function cl(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=Jr));else if(4!==r&&null!==(e=e.child))for(cl(e,t,n),e=e.sibling;null!==e;)cl(e,t,n),e=e.sibling}function ul(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&null!==(e=e.child))for(ul(e,t,n),e=e.sibling;null!==e;)ul(e,t,n),e=e.sibling}var dl=null,pl=!1;function fl(e,t,n){for(n=n.child;null!==n;)ml(e,t,n),n=n.sibling}function ml(e,t,n){if(ot&&"function"==typeof ot.onCommitFiberUnmount)try{ot.onCommitFiberUnmount(at,n)}catch(s){}switch(n.tag){case 5:Ys||el(n,t);case 6:var r=dl,a=pl;dl=null,fl(e,t,n),pl=a,null!==(dl=r)&&(pl?(e=dl,n=n.stateNode,8===e.nodeType?e.parentNode.removeChild(n):e.removeChild(n)):dl.removeChild(n.stateNode));break;case 18:null!==dl&&(pl?(e=dl,n=n.stateNode,8===e.nodeType?la(e.parentNode,n):1===e.nodeType&&la(e,n),Ut(e)):la(dl,n.stateNode));break;case 4:r=dl,a=pl,dl=n.stateNode.containerInfo,pl=!0,fl(e,t,n),dl=r,pl=a;break;case 0:case 11:case 14:case 15:if(!Ys&&(null!==(r=n.updateQueue)&&null!==(r=r.lastEffect))){a=r=r.next;do{var o=a,i=o.destroy;o=o.tag,void 0!==i&&(0!=(2&o)||0!=(4&o))&&tl(n,t,i),a=a.next}while(a!==r)}fl(e,t,n);break;case 1:if(!Ys&&(el(n,t),"function"==typeof(r=n.stateNode).componentWillUnmount))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(s){Ec(n,t,s)}fl(e,t,n);break;case 21:fl(e,t,n);break;case 22:1&n.mode?(Ys=(r=Ys)||null!==n.memoizedState,fl(e,t,n),Ys=r):fl(e,t,n);break;default:fl(e,t,n)}}function hl(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new Xs),t.forEach((function(t){var r=Ac.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))}))}}function gl(e,t){var n=t.deletions;if(null!==n)for(var r=0;r<n.length;r++){var a=n[r];try{var i=e,s=t,l=s;e:for(;null!==l;){switch(l.tag){case 5:dl=l.stateNode,pl=!1;break e;case 3:case 4:dl=l.stateNode.containerInfo,pl=!0;break e}l=l.return}if(null===dl)throw Error(o(160));ml(i,s,a),dl=null,pl=!1;var c=a.alternate;null!==c&&(c.return=null),a.return=null}catch(u){Ec(a,t,u)}}if(12854&t.subtreeFlags)for(t=t.child;null!==t;)bl(t,e),t=t.sibling}function bl(e,t){var n=e.alternate,r=e.flags;switch(e.tag){case 0:case 11:case 14:case 15:if(gl(t,e),vl(e),4&r){try{rl(3,e,e.return),al(3,e)}catch(g){Ec(e,e.return,g)}try{rl(5,e,e.return)}catch(g){Ec(e,e.return,g)}}break;case 1:gl(t,e),vl(e),512&r&&null!==n&&el(n,n.return);break;case 5:if(gl(t,e),vl(e),512&r&&null!==n&&el(n,n.return),32&e.flags){var a=e.stateNode;try{pe(a,"")}catch(g){Ec(e,e.return,g)}}if(4&r&&null!=(a=e.stateNode)){var i=e.memoizedProps,s=null!==n?n.memoizedProps:i,l=e.type,c=e.updateQueue;if(e.updateQueue=null,null!==c)try{"input"===l&&"radio"===i.type&&null!=i.name&&Y(a,i),ye(l,s);var u=ye(l,i);for(s=0;s<c.length;s+=2){var d=c[s],p=c[s+1];"style"===d?ge(a,p):"dangerouslySetInnerHTML"===d?de(a,p):"children"===d?pe(a,p):y(a,d,p,u)}switch(l){case"input":X(a,i);break;case"textarea":oe(a,i);break;case"select":var f=a._wrapperState.wasMultiple;a._wrapperState.wasMultiple=!!i.multiple;var m=i.value;null!=m?ne(a,!!i.multiple,m,!1):f!==!!i.multiple&&(null!=i.defaultValue?ne(a,!!i.multiple,i.defaultValue,!0):ne(a,!!i.multiple,i.multiple?[]:"",!1))}a[fa]=i}catch(g){Ec(e,e.return,g)}}break;case 6:if(gl(t,e),vl(e),4&r){if(null===e.stateNode)throw Error(o(162));a=e.stateNode,i=e.memoizedProps;try{a.nodeValue=i}catch(g){Ec(e,e.return,g)}}break;case 3:if(gl(t,e),vl(e),4&r&&null!==n&&n.memoizedState.isDehydrated)try{Ut(t.containerInfo)}catch(g){Ec(e,e.return,g)}break;case 4:default:gl(t,e),vl(e);break;case 13:gl(t,e),vl(e),8192&(a=e.child).flags&&(i=null!==a.memoizedState,a.stateNode.isHidden=i,!i||null!==a.alternate&&null!==a.alternate.memoizedState||(Ul=Ye())),4&r&&hl(e);break;case 22:if(d=null!==n&&null!==n.memoizedState,1&e.mode?(Ys=(u=Ys)||d,gl(t,e),Ys=u):gl(t,e),vl(e),8192&r){if(u=null!==e.memoizedState,(e.stateNode.isHidden=u)&&!d&&0!=(1&e.mode))for(Js=e,d=e.child;null!==d;){for(p=Js=d;null!==Js;){switch(m=(f=Js).child,f.tag){case 0:case 11:case 14:case 15:rl(4,f,f.return);break;case 1:el(f,f.return);var h=f.stateNode;if("function"==typeof h.componentWillUnmount){r=f,n=f.return;try{t=r,h.props=t.memoizedProps,h.state=t.memoizedState,h.componentWillUnmount()}catch(g){Ec(r,n,g)}}break;case 5:el(f,f.return);break;case 22:if(null!==f.memoizedState){kl(p);continue}}null!==m?(m.return=f,Js=m):kl(p)}d=d.sibling}e:for(d=null,p=e;;){if(5===p.tag){if(null===d){d=p;try{a=p.stateNode,u?"function"==typeof(i=a.style).setProperty?i.setProperty("display","none","important"):i.display="none":(l=p.stateNode,s=null!=(c=p.memoizedProps.style)&&c.hasOwnProperty("display")?c.display:null,l.style.display=he("display",s))}catch(g){Ec(e,e.return,g)}}}else if(6===p.tag){if(null===d)try{p.stateNode.nodeValue=u?"":p.memoizedProps}catch(g){Ec(e,e.return,g)}}else if((22!==p.tag&&23!==p.tag||null===p.memoizedState||p===e)&&null!==p.child){p.child.return=p,p=p.child;continue}if(p===e)break e;for(;null===p.sibling;){if(null===p.return||p.return===e)break e;d===p&&(d=null),p=p.return}d===p&&(d=null),p.sibling.return=p.return,p=p.sibling}}break;case 19:gl(t,e),vl(e),4&r&&hl(e);case 21:}}function vl(e){var t=e.flags;if(2&t){try{e:{for(var n=e.return;null!==n;){if(sl(n)){var r=n;break e}n=n.return}throw Error(o(160))}switch(r.tag){case 5:var a=r.stateNode;32&r.flags&&(pe(a,""),r.flags&=-33),ul(e,ll(e),a);break;case 3:case 4:var i=r.stateNode.containerInfo;cl(e,ll(e),i);break;default:throw Error(o(161))}}catch(s){Ec(e,e.return,s)}e.flags&=-3}4096&t&&(e.flags&=-4097)}function yl(e,t,n){Js=e,xl(e,t,n)}function xl(e,t,n){for(var r=0!=(1&e.mode);null!==Js;){var a=Js,o=a.child;if(22===a.tag&&r){var i=null!==a.memoizedState||Ks;if(!i){var s=a.alternate,l=null!==s&&null!==s.memoizedState||Ys;s=Ks;var c=Ys;if(Ks=i,(Ys=l)&&!c)for(Js=a;null!==Js;)l=(i=Js).child,22===i.tag&&null!==i.memoizedState?Sl(a):null!==l?(l.return=i,Js=l):Sl(a);for(;null!==o;)Js=o,xl(o,t,n),o=o.sibling;Js=a,Ks=s,Ys=c}wl(e)}else 0!=(8772&a.subtreeFlags)&&null!==o?(o.return=a,Js=o):wl(e)}}function wl(e){for(;null!==Js;){var t=Js;if(0!=(8772&t.flags)){var n=t.alternate;try{if(0!=(8772&t.flags))switch(t.tag){case 0:case 11:case 15:Ys||al(5,t);break;case 1:var r=t.stateNode;if(4&t.flags&&!Ys)if(null===n)r.componentDidMount();else{var a=t.elementType===t.type?n.memoizedProps:bo(t.type,n.memoizedProps);r.componentDidUpdate(a,n.memoizedState,r.__reactInternalSnapshotBeforeUpdate)}var i=t.updateQueue;null!==i&&zo(t,i,r);break;case 3:var s=t.updateQueue;if(null!==s){if(n=null,null!==t.child)switch(t.child.tag){case 5:case 1:n=t.child.stateNode}zo(t,s,n)}break;case 5:var l=t.stateNode;if(null===n&&4&t.flags){n=l;var c=t.memoizedProps;switch(t.type){case"button":case"input":case"select":case"textarea":c.autoFocus&&n.focus();break;case"img":c.src&&(n.src=c.src)}}break;case 6:case 4:case 12:case 19:case 17:case 21:case 22:case 23:case 25:break;case 13:if(null===t.memoizedState){var u=t.alternate;if(null!==u){var d=u.memoizedState;if(null!==d){var p=d.dehydrated;null!==p&&Ut(p)}}}break;default:throw Error(o(163))}Ys||512&t.flags&&ol(t)}catch(f){Ec(t,t.return,f)}}if(t===e){Js=null;break}if(null!==(n=t.sibling)){n.return=t.return,Js=n;break}Js=t.return}}function kl(e){for(;null!==Js;){var t=Js;if(t===e){Js=null;break}var n=t.sibling;if(null!==n){n.return=t.return,Js=n;break}Js=t.return}}function Sl(e){for(;null!==Js;){var t=Js;try{switch(t.tag){case 0:case 11:case 15:var n=t.return;try{al(4,t)}catch(l){Ec(t,n,l)}break;case 1:var r=t.stateNode;if("function"==typeof r.componentDidMount){var a=t.return;try{r.componentDidMount()}catch(l){Ec(t,a,l)}}var o=t.return;try{ol(t)}catch(l){Ec(t,o,l)}break;case 5:var i=t.return;try{ol(t)}catch(l){Ec(t,i,l)}}}catch(l){Ec(t,t.return,l)}if(t===e){Js=null;break}var s=t.sibling;if(null!==s){s.return=t.return,Js=s;break}Js=t.return}}var _l,El=Math.ceil,Cl=x.ReactCurrentDispatcher,Tl=x.ReactCurrentOwner,jl=x.ReactCurrentBatchConfig,Al=0,Ll=null,Rl=null,Nl=0,Pl=0,Ol=_a(0),Il=0,Dl=null,Ml=0,Fl=0,zl=0,Bl=null,$l=null,Ul=0,ql=1/0,Hl=null,Zl=!1,Gl=null,Vl=null,Wl=!1,Ql=null,Kl=0,Yl=0,Xl=null,Jl=-1,ec=0;function tc(){return 0!=(6&Al)?Ye():-1!==Jl?Jl:Jl=Ye()}function nc(e){return 0==(1&e.mode)?1:0!=(2&Al)&&0!==Nl?Nl&-Nl:null!==go.transition?(0===ec&&(ec=ht()),ec):0!==(e=yt)?e:e=void 0===(e=window.event)?16:Kt(e.type)}function rc(e,t,n,r){if(50<Yl)throw Yl=0,Xl=null,Error(o(185));bt(e,n,r),0!=(2&Al)&&e===Ll||(e===Ll&&(0==(2&Al)&&(Fl|=n),4===Il&&lc(e,Nl)),ac(e,r),1===n&&0===Al&&0==(1&t.mode)&&(ql=Ye()+500,za&&Ua()))}function ac(e,t){var n=e.callbackNode;!function(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,a=e.expirationTimes,o=e.pendingLanes;0<o;){var i=31-it(o),s=1<<i,l=a[i];-1===l?0!=(s&n)&&0==(s&r)||(a[i]=ft(s,t)):l<=t&&(e.expiredLanes|=s),o&=~s}}(e,t);var r=pt(e,e===Ll?Nl:0);if(0===r)null!==n&&We(n),e.callbackNode=null,e.callbackPriority=0;else if(t=r&-r,e.callbackPriority!==t){if(null!=n&&We(n),1===t)0===e.tag?function(e){za=!0,$a(e)}(cc.bind(null,e)):$a(cc.bind(null,e)),ia((function(){0==(6&Al)&&Ua()})),n=null;else{switch(xt(r)){case 1:n=Je;break;case 4:n=et;break;case 16:default:n=tt;break;case 536870912:n=rt}n=Lc(n,oc.bind(null,e))}e.callbackPriority=t,e.callbackNode=n}}function oc(e,t){if(Jl=-1,ec=0,0!=(6&Al))throw Error(o(327));var n=e.callbackNode;if(Sc()&&e.callbackNode!==n)return null;var r=pt(e,e===Ll?Nl:0);if(0===r)return null;if(0!=(30&r)||0!=(r&e.expiredLanes)||t)t=bc(e,r);else{t=r;var a=Al;Al|=2;var i=hc();for(Ll===e&&Nl===t||(Hl=null,ql=Ye()+500,fc(e,t));;)try{yc();break}catch(l){mc(e,l)}ko(),Cl.current=i,Al=a,null!==Rl?t=0:(Ll=null,Nl=0,t=Il)}if(0!==t){if(2===t&&(0!==(a=mt(e))&&(r=a,t=ic(e,a))),1===t)throw n=Dl,fc(e,0),lc(e,r),ac(e,Ye()),n;if(6===t)lc(e,r);else{if(a=e.current.alternate,0==(30&r)&&!function(e){for(var t=e;;){if(16384&t.flags){var n=t.updateQueue;if(null!==n&&null!==(n=n.stores))for(var r=0;r<n.length;r++){var a=n[r],o=a.getSnapshot;a=a.value;try{if(!sr(o(),a))return!1}catch(s){return!1}}}if(n=t.child,16384&t.subtreeFlags&&null!==n)n.return=t,t=n;else{if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return!0;t=t.return}t.sibling.return=t.return,t=t.sibling}}return!0}(a)&&(2===(t=bc(e,r))&&(0!==(i=mt(e))&&(r=i,t=ic(e,i))),1===t))throw n=Dl,fc(e,0),lc(e,r),ac(e,Ye()),n;switch(e.finishedWork=a,e.finishedLanes=r,t){case 0:case 1:throw Error(o(345));case 2:case 5:kc(e,$l,Hl);break;case 3:if(lc(e,r),(130023424&r)===r&&10<(t=Ul+500-Ye())){if(0!==pt(e,0))break;if(((a=e.suspendedLanes)&r)!==r){tc(),e.pingedLanes|=e.suspendedLanes&a;break}e.timeoutHandle=ra(kc.bind(null,e,$l,Hl),t);break}kc(e,$l,Hl);break;case 4:if(lc(e,r),(4194240&r)===r)break;for(t=e.eventTimes,a=-1;0<r;){var s=31-it(r);i=1<<s,(s=t[s])>a&&(a=s),r&=~i}if(r=a,10<(r=(120>(r=Ye()-r)?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*El(r/1960))-r)){e.timeoutHandle=ra(kc.bind(null,e,$l,Hl),r);break}kc(e,$l,Hl);break;default:throw Error(o(329))}}}return ac(e,Ye()),e.callbackNode===n?oc.bind(null,e):null}function ic(e,t){var n=Bl;return e.current.memoizedState.isDehydrated&&(fc(e,t).flags|=256),2!==(e=bc(e,t))&&(t=$l,$l=n,null!==t&&sc(t)),e}function sc(e){null===$l?$l=e:$l.push.apply($l,e)}function lc(e,t){for(t&=~zl,t&=~Fl,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0<t;){var n=31-it(t),r=1<<n;e[n]=-1,t&=~r}}function cc(e){if(0!=(6&Al))throw Error(o(327));Sc();var t=pt(e,0);if(0==(1&t))return ac(e,Ye()),null;var n=bc(e,t);if(0!==e.tag&&2===n){var r=mt(e);0!==r&&(t=r,n=ic(e,r))}if(1===n)throw n=Dl,fc(e,0),lc(e,t),ac(e,Ye()),n;if(6===n)throw Error(o(345));return e.finishedWork=e.current.alternate,e.finishedLanes=t,kc(e,$l,Hl),ac(e,Ye()),null}function uc(e,t){var n=Al;Al|=1;try{return e(t)}finally{0===(Al=n)&&(ql=Ye()+500,za&&Ua())}}function dc(e){null!==Ql&&0===Ql.tag&&0==(6&Al)&&Sc();var t=Al;Al|=1;var n=jl.transition,r=yt;try{if(jl.transition=null,yt=1,e)return e()}finally{yt=r,jl.transition=n,0==(6&(Al=t))&&Ua()}}function pc(){Pl=Ol.current,Ea(Ol)}function fc(e,t){e.finishedWork=null,e.finishedLanes=0;var n=e.timeoutHandle;if(-1!==n&&(e.timeoutHandle=-1,aa(n)),null!==Rl)for(n=Rl.return;null!==n;){var r=n;switch(to(r),r.tag){case 1:null!=(r=r.type.childContextTypes)&&Pa();break;case 3:oi(),Ea(Aa),Ea(ja),di();break;case 5:si(r);break;case 4:oi();break;case 13:case 19:Ea(li);break;case 10:So(r.type._context);break;case 22:case 23:pc()}n=n.return}if(Ll=e,Rl=e=Oc(e.current,null),Nl=Pl=t,Il=0,Dl=null,zl=Fl=Ml=0,$l=Bl=null,null!==To){for(t=0;t<To.length;t++)if(null!==(r=(n=To[t]).interleaved)){n.interleaved=null;var a=r.next,o=n.pending;if(null!==o){var i=o.next;o.next=a,r.next=i}n.pending=r}To=null}return e}function mc(e,t){for(;;){var n=Rl;try{if(ko(),pi.current=is,vi){for(var r=hi.memoizedState;null!==r;){var a=r.queue;null!==a&&(a.pending=null),r=r.next}vi=!1}if(mi=0,bi=gi=hi=null,yi=!1,xi=0,Tl.current=null,null===n||null===n.return){Il=1,Dl=t,Rl=null;break}e:{var i=e,s=n.return,l=n,c=t;if(t=Nl,l.flags|=32768,null!==c&&"object"==typeof c&&"function"==typeof c.then){var u=c,d=l,p=d.tag;if(0==(1&d.mode)&&(0===p||11===p||15===p)){var f=d.alternate;f?(d.updateQueue=f.updateQueue,d.memoizedState=f.memoizedState,d.lanes=f.lanes):(d.updateQueue=null,d.memoizedState=null)}var m=bs(s);if(null!==m){m.flags&=-257,vs(m,s,l,0,t),1&m.mode&&gs(i,u,t),c=u;var h=(t=m).updateQueue;if(null===h){var g=new Set;g.add(c),t.updateQueue=g}else h.add(c);break e}if(0==(1&t)){gs(i,u,t),gc();break e}c=Error(o(426))}else if(ao&&1&l.mode){var b=bs(s);if(null!==b){0==(65536&b.flags)&&(b.flags|=256),vs(b,s,l,0,t),ho(us(c,l));break e}}i=c=us(c,l),4!==Il&&(Il=2),null===Bl?Bl=[i]:Bl.push(i),i=s;do{switch(i.tag){case 3:i.flags|=65536,t&=-t,i.lanes|=t,Mo(i,ms(0,c,t));break e;case 1:l=c;var v=i.type,y=i.stateNode;if(0==(128&i.flags)&&("function"==typeof v.getDerivedStateFromError||null!==y&&"function"==typeof y.componentDidCatch&&(null===Vl||!Vl.has(y)))){i.flags|=65536,t&=-t,i.lanes|=t,Mo(i,hs(i,l,t));break e}}i=i.return}while(null!==i)}wc(n)}catch(x){t=x,Rl===n&&null!==n&&(Rl=n=n.return);continue}break}}function hc(){var e=Cl.current;return Cl.current=is,null===e?is:e}function gc(){0!==Il&&3!==Il&&2!==Il||(Il=4),null===Ll||0==(268435455&Ml)&&0==(268435455&Fl)||lc(Ll,Nl)}function bc(e,t){var n=Al;Al|=2;var r=hc();for(Ll===e&&Nl===t||(Hl=null,fc(e,t));;)try{vc();break}catch(a){mc(e,a)}if(ko(),Al=n,Cl.current=r,null!==Rl)throw Error(o(261));return Ll=null,Nl=0,Il}function vc(){for(;null!==Rl;)xc(Rl)}function yc(){for(;null!==Rl&&!Qe();)xc(Rl)}function xc(e){var t=_l(e.alternate,e,Pl);e.memoizedProps=e.pendingProps,null===t?wc(e):Rl=t,Tl.current=null}function wc(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(32768&t.flags)){if(null!==(n=Ws(n,t,Pl)))return void(Rl=n)}else{if(null!==(n=Qs(n,t)))return n.flags&=32767,void(Rl=n);if(null===e)return Il=6,void(Rl=null);e.flags|=32768,e.subtreeFlags=0,e.deletions=null}if(null!==(t=t.sibling))return void(Rl=t);Rl=t=e}while(null!==t);0===Il&&(Il=5)}function kc(e,t,n){var r=yt,a=jl.transition;try{jl.transition=null,yt=1,function(e,t,n,r){do{Sc()}while(null!==Ql);if(0!=(6&Al))throw Error(o(327));n=e.finishedWork;var a=e.finishedLanes;if(null===n)return null;if(e.finishedWork=null,e.finishedLanes=0,n===e.current)throw Error(o(177));e.callbackNode=null,e.callbackPriority=0;var i=n.lanes|n.childLanes;if(function(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0<n;){var a=31-it(n),o=1<<a;t[a]=0,r[a]=-1,e[a]=-1,n&=~o}}(e,i),e===Ll&&(Rl=Ll=null,Nl=0),0==(2064&n.subtreeFlags)&&0==(2064&n.flags)||Wl||(Wl=!0,Lc(tt,(function(){return Sc(),null}))),i=0!=(15990&n.flags),0!=(15990&n.subtreeFlags)||i){i=jl.transition,jl.transition=null;var s=yt;yt=1;var l=Al;Al|=4,Tl.current=null,function(e,t){if(ea=Ht,fr(e=pr())){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{var r=(n=(n=e.ownerDocument)&&n.defaultView||window).getSelection&&n.getSelection();if(r&&0!==r.rangeCount){n=r.anchorNode;var a=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch(w){n=null;break e}var s=0,l=-1,c=-1,u=0,d=0,p=e,f=null;t:for(;;){for(var m;p!==n||0!==a&&3!==p.nodeType||(l=s+a),p!==i||0!==r&&3!==p.nodeType||(c=s+r),3===p.nodeType&&(s+=p.nodeValue.length),null!==(m=p.firstChild);)f=p,p=m;for(;;){if(p===e)break t;if(f===n&&++u===a&&(l=s),f===i&&++d===r&&(c=s),null!==(m=p.nextSibling))break;f=(p=f).parentNode}p=m}n=-1===l||-1===c?null:{start:l,end:c}}else n=null}n=n||{start:0,end:0}}else n=null;for(ta={focusedElem:e,selectionRange:n},Ht=!1,Js=t;null!==Js;)if(e=(t=Js).child,0!=(1028&t.subtreeFlags)&&null!==e)e.return=t,Js=e;else for(;null!==Js;){t=Js;try{var h=t.alternate;if(0!=(1024&t.flags))switch(t.tag){case 0:case 11:case 15:case 5:case 6:case 4:case 17:break;case 1:if(null!==h){var g=h.memoizedProps,b=h.memoizedState,v=t.stateNode,y=v.getSnapshotBeforeUpdate(t.elementType===t.type?g:bo(t.type,g),b);v.__reactInternalSnapshotBeforeUpdate=y}break;case 3:var x=t.stateNode.containerInfo;1===x.nodeType?x.textContent="":9===x.nodeType&&x.documentElement&&x.removeChild(x.documentElement);break;default:throw Error(o(163))}}catch(w){Ec(t,t.return,w)}if(null!==(e=t.sibling)){e.return=t.return,Js=e;break}Js=t.return}h=nl,nl=!1}(e,n),bl(n,e),mr(ta),Ht=!!ea,ta=ea=null,e.current=n,yl(n,e,a),Ke(),Al=l,yt=s,jl.transition=i}else e.current=n;if(Wl&&(Wl=!1,Ql=e,Kl=a),i=e.pendingLanes,0===i&&(Vl=null),function(e){if(ot&&"function"==typeof ot.onCommitFiberRoot)try{ot.onCommitFiberRoot(at,e,void 0,128==(128&e.current.flags))}catch(t){}}(n.stateNode),ac(e,Ye()),null!==t)for(r=e.onRecoverableError,n=0;n<t.length;n++)a=t[n],r(a.value,{componentStack:a.stack,digest:a.digest});if(Zl)throw Zl=!1,e=Gl,Gl=null,e;0!=(1&Kl)&&0!==e.tag&&Sc(),i=e.pendingLanes,0!=(1&i)?e===Xl?Yl++:(Yl=0,Xl=e):Yl=0,Ua()}(e,t,n,r)}finally{jl.transition=a,yt=r}return null}function Sc(){if(null!==Ql){var e=xt(Kl),t=jl.transition,n=yt;try{if(jl.transition=null,yt=16>e?16:e,null===Ql)var r=!1;else{if(e=Ql,Ql=null,Kl=0,0!=(6&Al))throw Error(o(331));var a=Al;for(Al|=4,Js=e.current;null!==Js;){var i=Js,s=i.child;if(0!=(16&Js.flags)){var l=i.deletions;if(null!==l){for(var c=0;c<l.length;c++){var u=l[c];for(Js=u;null!==Js;){var d=Js;switch(d.tag){case 0:case 11:case 15:rl(8,d,i)}var p=d.child;if(null!==p)p.return=d,Js=p;else for(;null!==Js;){var f=(d=Js).sibling,m=d.return;if(il(d),d===u){Js=null;break}if(null!==f){f.return=m,Js=f;break}Js=m}}}var h=i.alternate;if(null!==h){var g=h.child;if(null!==g){h.child=null;do{var b=g.sibling;g.sibling=null,g=b}while(null!==g)}}Js=i}}if(0!=(2064&i.subtreeFlags)&&null!==s)s.return=i,Js=s;else e:for(;null!==Js;){if(0!=(2048&(i=Js).flags))switch(i.tag){case 0:case 11:case 15:rl(9,i,i.return)}var v=i.sibling;if(null!==v){v.return=i.return,Js=v;break e}Js=i.return}}var y=e.current;for(Js=y;null!==Js;){var x=(s=Js).child;if(0!=(2064&s.subtreeFlags)&&null!==x)x.return=s,Js=x;else e:for(s=y;null!==Js;){if(0!=(2048&(l=Js).flags))try{switch(l.tag){case 0:case 11:case 15:al(9,l)}}catch(k){Ec(l,l.return,k)}if(l===s){Js=null;break e}var w=l.sibling;if(null!==w){w.return=l.return,Js=w;break e}Js=l.return}}if(Al=a,Ua(),ot&&"function"==typeof ot.onPostCommitFiberRoot)try{ot.onPostCommitFiberRoot(at,e)}catch(k){}r=!0}return r}finally{yt=n,jl.transition=t}}return!1}function _c(e,t,n){e=Io(e,t=ms(0,t=us(n,t),1),1),t=tc(),null!==e&&(bt(e,1,t),ac(e,t))}function Ec(e,t,n){if(3===e.tag)_c(e,e,n);else for(;null!==t;){if(3===t.tag){_c(t,e,n);break}if(1===t.tag){var r=t.stateNode;if("function"==typeof t.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===Vl||!Vl.has(r))){t=Io(t,e=hs(t,e=us(n,e),1),1),e=tc(),null!==t&&(bt(t,1,e),ac(t,e));break}}t=t.return}}function Cc(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),t=tc(),e.pingedLanes|=e.suspendedLanes&n,Ll===e&&(Nl&n)===n&&(4===Il||3===Il&&(130023424&Nl)===Nl&&500>Ye()-Ul?fc(e,0):zl|=n),ac(e,t)}function Tc(e,t){0===t&&(0==(1&e.mode)?t=1:(t=ut,0==(130023424&(ut<<=1))&&(ut=4194304)));var n=tc();null!==(e=Lo(e,t))&&(bt(e,t,n),ac(e,n))}function jc(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),Tc(e,n)}function Ac(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,a=e.memoizedState;null!==a&&(n=a.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(o(314))}null!==r&&r.delete(t),Tc(e,n)}function Lc(e,t){return Ve(e,t)}function Rc(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Nc(e,t,n,r){return new Rc(e,t,n,r)}function Pc(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Oc(e,t){var n=e.alternate;return null===n?((n=Nc(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=14680064&e.flags,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Ic(e,t,n,r,a,i){var s=2;if(r=e,"function"==typeof e)Pc(e)&&(s=1);else if("string"==typeof e)s=5;else e:switch(e){case S:return Dc(n.children,a,i,t);case _:s=8,a|=8;break;case E:return(e=Nc(12,n,t,2|a)).elementType=E,e.lanes=i,e;case A:return(e=Nc(13,n,t,a)).elementType=A,e.lanes=i,e;case L:return(e=Nc(19,n,t,a)).elementType=L,e.lanes=i,e;case P:return Mc(n,a,i,t);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case C:s=10;break e;case T:s=9;break e;case j:s=11;break e;case R:s=14;break e;case N:s=16,r=null;break e}throw Error(o(130,null==e?e:typeof e,""))}return(t=Nc(s,n,t,a)).elementType=e,t.type=r,t.lanes=i,t}function Dc(e,t,n,r){return(e=Nc(7,e,r,t)).lanes=n,e}function Mc(e,t,n,r){return(e=Nc(22,e,r,t)).elementType=P,e.lanes=n,e.stateNode={isHidden:!1},e}function Fc(e,t,n){return(e=Nc(6,e,null,t)).lanes=n,e}function zc(e,t,n){return(t=Nc(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Bc(e,t,n,r,a){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=gt(0),this.expirationTimes=gt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=gt(0),this.identifierPrefix=r,this.onRecoverableError=a,this.mutableSourceEagerHydrationData=null}function $c(e,t,n,r,a,o,i,s,l){return e=new Bc(e,t,n,s,l),1===t?(t=1,!0===o&&(t|=8)):t=0,o=Nc(3,null,null,t),e.current=o,o.stateNode=e,o.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},No(o),e}function Uc(e){if(!e)return Ta;e:{if(Ue(e=e._reactInternals)!==e||1!==e.tag)throw Error(o(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(Na(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);throw Error(o(171))}if(1===e.tag){var n=e.type;if(Na(n))return Ia(e,n,t)}return t}function qc(e,t,n,r,a,o,i,s,l){return(e=$c(n,r,!0,e,0,o,0,s,l)).context=Uc(null),n=e.current,(o=Oo(r=tc(),a=nc(n))).callback=null!=t?t:null,Io(n,o,a),e.current.lanes=a,bt(e,a,r),ac(e,r),e}function Hc(e,t,n,r){var a=t.current,o=tc(),i=nc(a);return n=Uc(n),null===t.context?t.context=n:t.pendingContext=n,(t=Oo(o,i)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),null!==(e=Io(a,t,i))&&(rc(e,a,i,o),Do(e,a,i)),i}function Zc(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function Gc(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n<t?n:t}}function Vc(e,t){Gc(e,t),(e=e.alternate)&&Gc(e,t)}_l=function(e,t,n){if(null!==e)if(e.memoizedProps!==t.pendingProps||Aa.current)xs=!0;else{if(0==(e.lanes&n)&&0==(128&t.flags))return xs=!1,function(e,t,n){switch(t.tag){case 3:Ls(t),mo();break;case 5:ii(t);break;case 1:Na(t.type)&&Da(t);break;case 4:ai(t,t.stateNode.containerInfo);break;case 10:var r=t.type._context,a=t.memoizedProps.value;Ca(vo,r._currentValue),r._currentValue=a;break;case 13:if(null!==(r=t.memoizedState))return null!==r.dehydrated?(Ca(li,1&li.current),t.flags|=128,null):0!=(n&t.child.childLanes)?Fs(e,t,n):(Ca(li,1&li.current),null!==(e=Zs(e,t,n))?e.sibling:null);Ca(li,1&li.current);break;case 19:if(r=0!=(n&t.childLanes),0!=(128&e.flags)){if(r)return qs(e,t,n);t.flags|=128}if(null!==(a=t.memoizedState)&&(a.rendering=null,a.tail=null,a.lastEffect=null),Ca(li,li.current),r)break;return null;case 22:case 23:return t.lanes=0,Es(e,t,n)}return Zs(e,t,n)}(e,t,n);xs=0!=(131072&e.flags)}else xs=!1,ao&&0!=(1048576&t.flags)&&Ja(t,Ga,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Hs(e,t),e=t.pendingProps;var a=Ra(t,ja.current);Eo(t,n),a=_i(null,t,r,e,a,n);var i=Ei();return t.flags|=1,"object"==typeof a&&null!==a&&"function"==typeof a.render&&void 0===a.$$typeof?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Na(r)?(i=!0,Da(t)):i=!1,t.memoizedState=null!==a.state&&void 0!==a.state?a.state:null,No(t),a.updater=Uo,t.stateNode=a,a._reactInternals=t,Go(t,r,e,n),t=As(null,t,r,!0,i,n)):(t.tag=0,ao&&i&&eo(t),ws(null,t,a,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Hs(e,t),e=t.pendingProps,r=(a=r._init)(r._payload),t.type=r,a=t.tag=function(e){if("function"==typeof e)return Pc(e)?1:0;if(null!=e){if((e=e.$$typeof)===j)return 11;if(e===R)return 14}return 2}(r),e=bo(r,e),a){case 0:t=Ts(null,t,r,e,n);break e;case 1:t=js(null,t,r,e,n);break e;case 11:t=ks(null,t,r,e,n);break e;case 14:t=Ss(null,t,r,bo(r.type,e),n);break e}throw Error(o(306,r,""))}return t;case 0:return r=t.type,a=t.pendingProps,Ts(e,t,r,a=t.elementType===r?a:bo(r,a),n);case 1:return r=t.type,a=t.pendingProps,js(e,t,r,a=t.elementType===r?a:bo(r,a),n);case 3:e:{if(Ls(t),null===e)throw Error(o(387));r=t.pendingProps,a=(i=t.memoizedState).element,Po(e,t),Fo(t,r,null,n);var s=t.memoizedState;if(r=s.element,i.isDehydrated){if(i={element:r,isDehydrated:!1,cache:s.cache,pendingSuspenseBoundaries:s.pendingSuspenseBoundaries,transitions:s.transitions},t.updateQueue.baseState=i,t.memoizedState=i,256&t.flags){t=Rs(e,t,r,n,a=us(Error(o(423)),t));break e}if(r!==a){t=Rs(e,t,r,n,a=us(Error(o(424)),t));break e}for(ro=ca(t.stateNode.containerInfo.firstChild),no=t,ao=!0,oo=null,n=Xo(t,null,r,n),t.child=n;n;)n.flags=-3&n.flags|4096,n=n.sibling}else{if(mo(),r===a){t=Zs(e,t,n);break e}ws(e,t,r,n)}t=t.child}return t;case 5:return ii(t),null===e&&co(t),r=t.type,a=t.pendingProps,i=null!==e?e.memoizedProps:null,s=a.children,na(r,a)?s=null:null!==i&&na(r,i)&&(t.flags|=32),Cs(e,t),ws(e,t,s,n),t.child;case 6:return null===e&&co(t),null;case 13:return Fs(e,t,n);case 4:return ai(t,t.stateNode.containerInfo),r=t.pendingProps,null===e?t.child=Yo(t,null,r,n):ws(e,t,r,n),t.child;case 11:return r=t.type,a=t.pendingProps,ks(e,t,r,a=t.elementType===r?a:bo(r,a),n);case 7:return ws(e,t,t.pendingProps,n),t.child;case 8:case 12:return ws(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,a=t.pendingProps,i=t.memoizedProps,s=a.value,Ca(vo,r._currentValue),r._currentValue=s,null!==i)if(sr(i.value,s)){if(i.children===a.children&&!Aa.current){t=Zs(e,t,n);break e}}else for(null!==(i=t.child)&&(i.return=t);null!==i;){var l=i.dependencies;if(null!==l){s=i.child;for(var c=l.firstContext;null!==c;){if(c.context===r){if(1===i.tag){(c=Oo(-1,n&-n)).tag=2;var u=i.updateQueue;if(null!==u){var d=(u=u.shared).pending;null===d?c.next=c:(c.next=d.next,d.next=c),u.pending=c}}i.lanes|=n,null!==(c=i.alternate)&&(c.lanes|=n),_o(i.return,n,t),l.lanes|=n;break}c=c.next}}else if(10===i.tag)s=i.type===t.type?null:i.child;else if(18===i.tag){if(null===(s=i.return))throw Error(o(341));s.lanes|=n,null!==(l=s.alternate)&&(l.lanes|=n),_o(s,n,t),s=i.sibling}else s=i.child;if(null!==s)s.return=i;else for(s=i;null!==s;){if(s===t){s=null;break}if(null!==(i=s.sibling)){i.return=s.return,s=i;break}s=s.return}i=s}ws(e,t,a.children,n),t=t.child}return t;case 9:return a=t.type,r=t.pendingProps.children,Eo(t,n),r=r(a=Co(a)),t.flags|=1,ws(e,t,r,n),t.child;case 14:return a=bo(r=t.type,t.pendingProps),Ss(e,t,r,a=bo(r.type,a),n);case 15:return _s(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,a=t.pendingProps,a=t.elementType===r?a:bo(r,a),Hs(e,t),t.tag=1,Na(r)?(e=!0,Da(t)):e=!1,Eo(t,n),Ho(t,r,a),Go(t,r,a,n),As(null,t,r,!0,e,n);case 19:return qs(e,t,n);case 22:return Es(e,t,n)}throw Error(o(156,t.tag))};var Wc="function"==typeof reportError?reportError:function(e){console.error(e)};function Qc(e){this._internalRoot=e}function Kc(e){this._internalRoot=e}function Yc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType)}function Xc(e){return!(!e||1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType&&(8!==e.nodeType||" react-mount-point-unstable "!==e.nodeValue))}function Jc(){}function eu(e,t,n,r,a){var o=n._reactRootContainer;if(o){var i=o;if("function"==typeof a){var s=a;a=function(){var e=Zc(i);s.call(e)}}Hc(t,i,e,a)}else i=function(e,t,n,r,a){if(a){if("function"==typeof r){var o=r;r=function(){var e=Zc(i);o.call(e)}}var i=qc(t,r,e,0,null,!1,0,"",Jc);return e._reactRootContainer=i,e[ma]=i.current,Ur(8===e.nodeType?e.parentNode:e),dc(),i}for(;a=e.lastChild;)e.removeChild(a);if("function"==typeof r){var s=r;r=function(){var e=Zc(l);s.call(e)}}var l=$c(e,0,!1,null,0,!1,0,"",Jc);return e._reactRootContainer=l,e[ma]=l.current,Ur(8===e.nodeType?e.parentNode:e),dc((function(){Hc(t,l,n,r)})),l}(n,t,e,a,r);return Zc(i)}Kc.prototype.render=Qc.prototype.render=function(e){var t=this._internalRoot;if(null===t)throw Error(o(409));Hc(e,t,null,null)},Kc.prototype.unmount=Qc.prototype.unmount=function(){var e=this._internalRoot;if(null!==e){this._internalRoot=null;var t=e.containerInfo;dc((function(){Hc(null,e,null,null)})),t[ma]=null}},Kc.prototype.unstable_scheduleHydration=function(e){if(e){var t=_t();e={blockedOn:null,target:e,priority:t};for(var n=0;n<Pt.length&&0!==t&&t<Pt[n].priority;n++);Pt.splice(n,0,e),0===n&&Mt(e)}},wt=function(e){switch(e.tag){case 3:var t=e.stateNode;if(t.current.memoizedState.isDehydrated){var n=dt(t.pendingLanes);0!==n&&(vt(t,1|n),ac(t,Ye()),0==(6&Al)&&(ql=Ye()+500,Ua()))}break;case 13:dc((function(){var t=Lo(e,1);if(null!==t){var n=tc();rc(t,e,1,n)}})),Vc(e,1)}},kt=function(e){if(13===e.tag){var t=Lo(e,134217728);if(null!==t)rc(t,e,134217728,tc());Vc(e,134217728)}},St=function(e){if(13===e.tag){var t=nc(e),n=Lo(e,t);if(null!==n)rc(n,e,t,tc());Vc(e,t)}},_t=function(){return yt},Et=function(e,t){var n=yt;try{return yt=e,t()}finally{yt=n}},ke=function(e,t,n){switch(t){case"input":if(X(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;t<n.length;t++){var r=n[t];if(r!==e&&r.form===e.form){var a=wa(r);if(!a)throw Error(o(90));V(r),X(r,a)}}}break;case"textarea":oe(e,n);break;case"select":null!=(t=n.value)&&ne(e,!!n.multiple,t,!1)}},je=uc,Ae=dc;var tu={usingClientEntryPoint:!1,Events:[ya,xa,wa,Ce,Te,uc]},nu={findFiberByHostInstance:va,bundleType:0,version:"18.2.0",rendererPackageName:"react-dom"},ru={bundleType:nu.bundleType,version:nu.version,rendererPackageName:nu.rendererPackageName,rendererConfig:nu.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:x.ReactCurrentDispatcher,findHostInstanceByFiber:function(e){return null===(e=Ze(e))?null:e.stateNode},findFiberByHostInstance:nu.findFiberByHostInstance||function(){return null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.2.0-next-9e3b772b8-20220608"};if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__){var au=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!au.isDisabled&&au.supportsFiber)try{at=au.inject(ru),ot=au}catch(ue){}}t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=tu,t.createPortal=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!Yc(t))throw Error(o(200));return function(e,t,n){var r=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:k,key:null==r?null:""+r,children:e,containerInfo:t,implementation:n}}(e,t,null,n)},t.createRoot=function(e,t){if(!Yc(e))throw Error(o(299));var n=!1,r="",a=Wc;return null!=t&&(!0===t.unstable_strictMode&&(n=!0),void 0!==t.identifierPrefix&&(r=t.identifierPrefix),void 0!==t.onRecoverableError&&(a=t.onRecoverableError)),t=$c(e,1,!1,null,0,n,0,r,a),e[ma]=t.current,Ur(8===e.nodeType?e.parentNode:e),new Qc(t)},t.findDOMNode=function(e){if(null==e)return null;if(1===e.nodeType)return e;var t=e._reactInternals;if(void 0===t){if("function"==typeof e.render)throw Error(o(188));throw e=Object.keys(e).join(","),Error(o(268,e))}return e=null===(e=Ze(t))?null:e.stateNode},t.flushSync=function(e){return dc(e)},t.hydrate=function(e,t,n){if(!Xc(t))throw Error(o(200));return eu(null,e,t,!0,n)},t.hydrateRoot=function(e,t,n){if(!Yc(e))throw Error(o(405));var r=null!=n&&n.hydratedSources||null,a=!1,i="",s=Wc;if(null!=n&&(!0===n.unstable_strictMode&&(a=!0),void 0!==n.identifierPrefix&&(i=n.identifierPrefix),void 0!==n.onRecoverableError&&(s=n.onRecoverableError)),t=qc(t,null,e,1,null!=n?n:null,a,0,i,s),e[ma]=t.current,Ur(e),r)for(e=0;e<r.length;e++)a=(a=(n=r[e])._getVersion)(n._source),null==t.mutableSourceEagerHydrationData?t.mutableSourceEagerHydrationData=[n,a]:t.mutableSourceEagerHydrationData.push(n,a);return new Kc(t)},t.render=function(e,t,n){if(!Xc(t))throw Error(o(200));return eu(null,e,t,!1,n)},t.unmountComponentAtNode=function(e){if(!Xc(e))throw Error(o(40));return!!e._reactRootContainer&&(dc((function(){eu(null,null,e,!1,(function(){e._reactRootContainer=null,e[ma]=null}))})),!0)},t.unstable_batchedUpdates=uc,t.unstable_renderSubtreeIntoContainer=function(e,t,n,r){if(!Xc(n))throw Error(o(200));if(null==e||void 0===e._reactInternals)throw Error(o(38));return eu(e,t,n,!1,r)},t.version="18.2.0-next-9e3b772b8-20220608"},745:(e,t,n)=>{"use strict";var r=n(3935);t.createRoot=r.createRoot,t.hydrateRoot=r.hydrateRoot},3935:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(4448)},9590:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,r="function"==typeof Set,a="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function o(e,i){if(e===i)return!0;if(e&&i&&"object"==typeof e&&"object"==typeof i){if(e.constructor!==i.constructor)return!1;var s,l,c,u;if(Array.isArray(e)){if((s=e.length)!=i.length)return!1;for(l=s;0!=l--;)if(!o(e[l],i[l]))return!1;return!0}if(n&&e instanceof Map&&i instanceof Map){if(e.size!==i.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!i.has(l.value[0]))return!1;for(u=e.entries();!(l=u.next()).done;)if(!o(l.value[1],i.get(l.value[0])))return!1;return!0}if(r&&e instanceof Set&&i instanceof Set){if(e.size!==i.size)return!1;for(u=e.entries();!(l=u.next()).done;)if(!i.has(l.value[0]))return!1;return!0}if(a&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(i)){if((s=e.length)!=i.length)return!1;for(l=s;0!=l--;)if(e[l]!==i[l])return!1;return!0}if(e.constructor===RegExp)return e.source===i.source&&e.flags===i.flags;if(e.valueOf!==Object.prototype.valueOf&&"function"==typeof e.valueOf&&"function"==typeof i.valueOf)return e.valueOf()===i.valueOf();if(e.toString!==Object.prototype.toString&&"function"==typeof e.toString&&"function"==typeof i.toString)return e.toString()===i.toString();if((s=(c=Object.keys(e)).length)!==Object.keys(i).length)return!1;for(l=s;0!=l--;)if(!Object.prototype.hasOwnProperty.call(i,c[l]))return!1;if(t&&e instanceof Element)return!1;for(l=s;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!e.$$typeof)&&!o(e[c[l]],i[c[l]]))return!1;return!0}return e!=e&&i!=i}e.exports=function(e,t){try{return o(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},405:(e,t,n)=>{"use strict";n.d(t,{B6:()=>Z,ql:()=>J});var r=n(7294),a=n(5697),o=n.n(a),i=n(9590),s=n.n(i),l=n(1143),c=n.n(l),u=n(6774),d=n.n(u);function p(){return p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},p.apply(this,arguments)}function f(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,m(e,t)}function m(e,t){return m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},m(e,t)}function h(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)t.indexOf(n=o[r])>=0||(a[n]=e[n]);return a}var g={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},b={rel:["amphtml","canonical","alternate"]},v={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},x=Object.keys(g).map((function(e){return g[e]})),w={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},k=Object.keys(w).reduce((function(e,t){return e[w[t]]=t,e}),{}),S=function(e,t){for(var n=e.length-1;n>=0;n-=1){var r=e[n];if(Object.prototype.hasOwnProperty.call(r,t))return r[t]}return null},_=function(e){var t=S(e,g.TITLE),n=S(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var r=S(e,"defaultTitle");return t||r||void 0},E=function(e){return S(e,"onChangeClientState")||function(){}},C=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return p({},e,t)}),{})},T=function(e,t){return t.filter((function(e){return void 0!==e[g.BASE]})).map((function(e){return e[g.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var r=Object.keys(n),a=0;a<r.length;a+=1){var o=r[a].toLowerCase();if(-1!==e.indexOf(o)&&n[o])return t.concat(n)}return t}),[])},j=function(e,t,n){var r={};return n.filter((function(t){return!!Array.isArray(t[e])||(void 0!==t[e]&&console&&"function"==typeof console.warn&&console.warn("Helmet: "+e+' should be of type "Array". Instead found type "'+typeof t[e]+'"'),!1)})).map((function(t){return t[e]})).reverse().reduce((function(e,n){var a={};n.filter((function(e){for(var n,o=Object.keys(e),i=0;i<o.length;i+=1){var s=o[i],l=s.toLowerCase();-1===t.indexOf(l)||"rel"===n&&"canonical"===e[n].toLowerCase()||"rel"===l&&"stylesheet"===e[l].toLowerCase()||(n=l),-1===t.indexOf(s)||"innerHTML"!==s&&"cssText"!==s&&"itemprop"!==s||(n=s)}if(!n||!e[n])return!1;var c=e[n].toLowerCase();return r[n]||(r[n]={}),a[n]||(a[n]={}),!r[n][c]&&(a[n][c]=!0,!0)})).reverse().forEach((function(t){return e.push(t)}));for(var o=Object.keys(a),i=0;i<o.length;i+=1){var s=o[i],l=p({},r[s],a[s]);r[s]=l}return e}),[]).reverse()},A=function(e,t){if(Array.isArray(e)&&e.length)for(var n=0;n<e.length;n+=1)if(e[n][t])return!0;return!1},L=function(e){return Array.isArray(e)?e.join(""):e},R=function(e,t){return Array.isArray(e)?e.reduce((function(e,n){return function(e,t){for(var n=Object.keys(e),r=0;r<n.length;r+=1)if(t[n[r]]&&t[n[r]].includes(e[n[r]]))return!0;return!1}(n,t)?e.priority.push(n):e.default.push(n),e}),{priority:[],default:[]}):{default:e}},N=function(e,t){var n;return p({},e,((n={})[t]=void 0,n))},P=[g.NOSCRIPT,g.SCRIPT,g.STYLE],O=function(e,t){return void 0===t&&(t=!0),!1===t?String(e):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},I=function(e){return Object.keys(e).reduce((function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r}),"")},D=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[w[n]||n]=e[n],t}),t)},M=function(e,t){return t.map((function(t,n){var a,o=((a={key:n})["data-rh"]=!0,a);return Object.keys(t).forEach((function(e){var n=w[e]||e;"innerHTML"===n||"cssText"===n?o.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:o[n]=t[e]})),r.createElement(e,o)}))},F=function(e,t,n){switch(e){case g.TITLE:return{toComponent:function(){return n=t.titleAttributes,(a={key:e=t.title})["data-rh"]=!0,o=D(n,a),[r.createElement(g.TITLE,o,e)];var e,n,a,o},toString:function(){return function(e,t,n,r){var a=I(n),o=L(t);return a?"<"+e+' data-rh="true" '+a+">"+O(o,r)+"</"+e+">":"<"+e+' data-rh="true">'+O(o,r)+"</"+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return D(t)},toString:function(){return I(t)}};default:return{toComponent:function(){return M(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,r){var a=Object.keys(r).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var a=void 0===r[t]?t:t+'="'+O(r[t],n)+'"';return e?e+" "+a:a}),""),o=r.innerHTML||r.cssText||"",i=-1===P.indexOf(e);return t+"<"+e+' data-rh="true" '+a+(i?"/>":">"+o+"</"+e+">")}),"")}(e,t,n)}}}},z=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,a=e.htmlAttributes,o=e.noscriptTags,i=e.styleTags,s=e.title,l=void 0===s?"":s,c=e.titleAttributes,u=e.linkTags,d=e.metaTags,p=e.scriptTags,f={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,r=e.encode,a=R(e.metaTags,y),o=R(t,b),i=R(n,v);return{priorityMethods:{toComponent:function(){return[].concat(M(g.META,a.priority),M(g.LINK,o.priority),M(g.SCRIPT,i.priority))},toString:function(){return F(g.META,a.priority,r)+" "+F(g.LINK,o.priority,r)+" "+F(g.SCRIPT,i.priority,r)}},metaTags:a.default,linkTags:o.default,scriptTags:i.default}}(e);f=m.priorityMethods,u=m.linkTags,d=m.metaTags,p=m.scriptTags}return{priority:f,base:F(g.BASE,t,r),bodyAttributes:F("bodyAttributes",n,r),htmlAttributes:F("htmlAttributes",a,r),link:F(g.LINK,u,r),meta:F(g.META,d,r),noscript:F(g.NOSCRIPT,o,r),script:F(g.SCRIPT,p,r),style:F(g.STYLE,i,r),title:F(g.TITLE,{title:l,titleAttributes:c},r)}},B=[],$=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?B:n.instances},add:function(e){(n.canUseDOM?B:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?B:n.instances).indexOf(e);(n.canUseDOM?B:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=z({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},U=r.createContext({}),q=o().shape({setHelmet:o().func,helmetInstances:o().shape({get:o().func,add:o().func,remove:o().func})}),H="undefined"!=typeof document,Z=function(e){function t(n){var r;return(r=e.call(this,n)||this).helmetData=new $(r.props.context,t.canUseDOM),r}return f(t,e),t.prototype.render=function(){return r.createElement(U.Provider,{value:this.helmetData.value},this.props.children)},t}(r.Component);Z.canUseDOM=H,Z.propTypes={context:o().shape({helmet:o().shape()}),children:o().node.isRequired},Z.defaultProps={context:{}},Z.displayName="HelmetProvider";var G=function(e,t){var n,r=document.head||document.querySelector(g.HEAD),a=r.querySelectorAll(e+"[data-rh]"),o=[].slice.call(a),i=[];return t&&t.length&&t.forEach((function(t){var r=document.createElement(e);for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&("innerHTML"===a?r.innerHTML=t.innerHTML:"cssText"===a?r.styleSheet?r.styleSheet.cssText=t.cssText:r.appendChild(document.createTextNode(t.cssText)):r.setAttribute(a,void 0===t[a]?"":t[a]));r.setAttribute("data-rh","true"),o.some((function(e,t){return n=t,r.isEqualNode(e)}))?o.splice(n,1):i.push(r)})),o.forEach((function(e){return e.parentNode.removeChild(e)})),i.forEach((function(e){return r.appendChild(e)})),{oldTags:o,newTags:i}},V=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute("data-rh"),a=r?r.split(","):[],o=[].concat(a),i=Object.keys(t),s=0;s<i.length;s+=1){var l=i[s],c=t[l]||"";n.getAttribute(l)!==c&&n.setAttribute(l,c),-1===a.indexOf(l)&&a.push(l);var u=o.indexOf(l);-1!==u&&o.splice(u,1)}for(var d=o.length-1;d>=0;d-=1)n.removeAttribute(o[d]);a.length===o.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==i.join(",")&&n.setAttribute("data-rh",i.join(","))}},W=function(e,t){var n=e.baseTag,r=e.htmlAttributes,a=e.linkTags,o=e.metaTags,i=e.noscriptTags,s=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,u=e.title,d=e.titleAttributes;V(g.BODY,e.bodyAttributes),V(g.HTML,r),function(e,t){void 0!==e&&document.title!==e&&(document.title=L(e)),V(g.TITLE,t)}(u,d);var p={baseTag:G(g.BASE,n),linkTags:G(g.LINK,a),metaTags:G(g.META,o),noscriptTags:G(g.NOSCRIPT,i),scriptTags:G(g.SCRIPT,l),styleTags:G(g.STYLE,c)},f={},m={};Object.keys(p).forEach((function(e){var t=p[e],n=t.newTags,r=t.oldTags;n.length&&(f[e]=n),r.length&&(m[e]=p[e].oldTags)})),t&&t(),s(e,f,m)},Q=null,K=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).rendered=!1,t}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!d()(e,this.props)},n.componentDidUpdate=function(){this.emitChange()},n.componentWillUnmount=function(){this.props.context.helmetInstances.remove(this),this.emitChange()},n.emitChange=function(){var e,t,n=this.props.context,r=n.setHelmet,a=null,o=(e=n.helmetInstances.get().map((function(e){var t=p({},e.props);return delete t.context,t})),{baseTag:T(["href"],e),bodyAttributes:C("bodyAttributes",e),defer:S(e,"defer"),encode:S(e,"encodeSpecialCharacters"),htmlAttributes:C("htmlAttributes",e),linkTags:j(g.LINK,["rel","href"],e),metaTags:j(g.META,["name","charset","http-equiv","property","itemprop"],e),noscriptTags:j(g.NOSCRIPT,["innerHTML"],e),onChangeClientState:E(e),scriptTags:j(g.SCRIPT,["src","innerHTML"],e),styleTags:j(g.STYLE,["cssText"],e),title:_(e),titleAttributes:C("titleAttributes",e),prioritizeSeoTags:A(e,"prioritizeSeoTags")});Z.canUseDOM?(t=o,Q&&cancelAnimationFrame(Q),t.defer?Q=requestAnimationFrame((function(){W(t,(function(){Q=null}))})):(W(t),Q=null)):z&&(a=z(o)),r(a)},n.init=function(){this.rendered||(this.rendered=!0,this.props.context.helmetInstances.add(this),this.emitChange())},n.render=function(){return this.init(),null},t}(r.Component);K.propTypes={context:q.isRequired},K.displayName="HelmetDispatcher";var Y=["children"],X=["children"],J=function(e){function t(){return e.apply(this,arguments)||this}f(t,e);var n=t.prototype;return n.shouldComponentUpdate=function(e){return!s()(N(this.props,"helmetData"),N(e,"helmetData"))},n.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case g.SCRIPT:case g.NOSCRIPT:return{innerHTML:t};case g.STYLE:return{cssText:t};default:throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren;return p({},r,((t={})[n.type]=[].concat(r[n.type]||[],[p({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,r=e.child,a=e.newProps,o=e.newChildProps,i=e.nestedChildren;switch(r.type){case g.TITLE:return p({},a,((t={})[r.type]=i,t.titleAttributes=p({},o),t));case g.BODY:return p({},a,{bodyAttributes:p({},o)});case g.HTML:return p({},a,{htmlAttributes:p({},o)});default:return p({},a,((n={})[r.type]=p({},o),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=p({},t);return Object.keys(e).forEach((function(t){var r;n=p({},n,((r={})[t]=e[t],r))})),n},n.warnOnInvalidChildren=function(e,t){return c()(x.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+x.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}</"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,a={};return r.Children.forEach(e,(function(e){if(e&&e.props){var r=e.props,o=r.children,i=h(r,Y),s=Object.keys(i).reduce((function(e,t){return e[k[t]||t]=i[t],e}),{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,o),l){case g.FRAGMENT:t=n.mapChildrenToProps(o,t);break;case g.LINK:case g.META:case g.NOSCRIPT:case g.SCRIPT:case g.STYLE:a=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:a,newChildProps:s,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:s,nestedChildren:o})}}})),this.mapArrayTypeChildrenToProps(a,t)},n.render=function(){var e=this.props,t=e.children,n=h(e,X),a=p({},n),o=n.helmetData;return t&&(a=this.mapChildrenToProps(t,a)),!o||o instanceof $||(o=new $(o.context,o.instances)),o?r.createElement(K,p({},a,{context:o.value,helmetData:void 0})):r.createElement(U.Consumer,null,(function(e){return r.createElement(K,p({},a,{context:e}))}))},t}(r.Component);J.propTypes={base:o().object,bodyAttributes:o().object,children:o().oneOfType([o().arrayOf(o().node),o().node]),defaultTitle:o().string,defer:o().bool,encodeSpecialCharacters:o().bool,htmlAttributes:o().object,link:o().arrayOf(o().object),meta:o().arrayOf(o().object),noscript:o().arrayOf(o().object),onChangeClientState:o().func,script:o().arrayOf(o().object),style:o().arrayOf(o().object),title:o().string,titleAttributes:o().object,titleTemplate:o().string,prioritizeSeoTags:o().bool,helmetData:o().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},9921:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,a=n?Symbol.for("react.portal"):60106,o=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,s=n?Symbol.for("react.profiler"):60114,l=n?Symbol.for("react.provider"):60109,c=n?Symbol.for("react.context"):60110,u=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,p=n?Symbol.for("react.forward_ref"):60112,f=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,g=n?Symbol.for("react.lazy"):60116,b=n?Symbol.for("react.block"):60121,v=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,x=n?Symbol.for("react.scope"):60119;function w(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case u:case d:case o:case s:case i:case f:return e;default:switch(e=e&&e.$$typeof){case c:case p:case g:case h:case l:return e;default:return t}}case a:return t}}}function k(e){return w(e)===d}t.AsyncMode=u,t.ConcurrentMode=d,t.ContextConsumer=c,t.ContextProvider=l,t.Element=r,t.ForwardRef=p,t.Fragment=o,t.Lazy=g,t.Memo=h,t.Portal=a,t.Profiler=s,t.StrictMode=i,t.Suspense=f,t.isAsyncMode=function(e){return k(e)||w(e)===u},t.isConcurrentMode=k,t.isContextConsumer=function(e){return w(e)===c},t.isContextProvider=function(e){return w(e)===l},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return w(e)===p},t.isFragment=function(e){return w(e)===o},t.isLazy=function(e){return w(e)===g},t.isMemo=function(e){return w(e)===h},t.isPortal=function(e){return w(e)===a},t.isProfiler=function(e){return w(e)===s},t.isStrictMode=function(e){return w(e)===i},t.isSuspense=function(e){return w(e)===f},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===o||e===d||e===s||e===i||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===h||e.$$typeof===l||e.$$typeof===c||e.$$typeof===p||e.$$typeof===v||e.$$typeof===y||e.$$typeof===x||e.$$typeof===b)},t.typeOf=w},9864:(e,t,n)=>{"use strict";e.exports=n(9921)},8356:(e,t,n)=>{"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function a(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i.apply(this,arguments)}var s=n(7294),l=n(5697),c=[],u=[];function d(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function p(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(r){var a=d(e[r]);a.loading?t.loading=!0:(t.loaded[r]=a.loaded,t.error=a.error),n.push(a.promise),a.promise.then((function(e){t.loaded[r]=e})).catch((function(e){t.error=e}))}))}catch(r){t.error=r}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function f(e,t){return s.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var d,p;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=i({loader:null,loading:null,delay:200,timeout:null,render:f,webpack:null,modules:null},t),h=null;function g(){return h||(h=e(m.loader)),h.promise}return c.push(g),"function"==typeof m.webpack&&u.push((function(){if((0,m.webpack)().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return g()})),p=d=function(t){function n(n){var r;return o(a(a(r=t.call(this,n)||this)),"retry",(function(){r.setState({error:null,loading:!0,timedOut:!1}),h=e(m.loader),r._loadModule()})),g(),r.state={error:h.error,pastDelay:!1,timedOut:!1,loading:h.loading,loaded:h.loaded},r}r(n,t),n.preload=function(){return g()};var i=n.prototype;return i.UNSAFE_componentWillMount=function(){this._loadModule()},i.componentDidMount=function(){this._mounted=!0},i._loadModule=function(){var e=this;if(this.context.loadable&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.loadable.report(t)})),h.loading){var t=function(t){e._mounted&&e.setState(t)};"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){t({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){t({timedOut:!0})}),m.timeout));var n=function(){t({error:h.error,loaded:h.loaded,loading:h.loading}),e._clearTimeouts()};h.promise.then((function(){return n(),null})).catch((function(e){return n(),null}))}},i.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},i._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},i.render=function(){return this.state.loading||this.state.error?s.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(s.Component),o(d,"contextTypes",{loadable:l.shape({report:l.func.isRequired})}),p}function h(e){return m(d,e)}h.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(p,e)};var g=function(e){function t(){return e.apply(this,arguments)||this}r(t,e);var n=t.prototype;return n.getChildContext=function(){return{loadable:{report:this.props.report}}},n.render=function(){return s.Children.only(this.props.children)},t}(s.Component);function b(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return b(e)}))}o(g,"propTypes",{report:l.func.isRequired}),o(g,"childContextTypes",{loadable:l.shape({report:l.func.isRequired}).isRequired}),h.Capture=g,h.preloadAll=function(){return new Promise((function(e,t){b(c).then(e,t)}))},h.preloadReady=function(){return new Promise((function(e,t){b(u).then(e,e)}))},e.exports=h},8790:(e,t,n)=>{"use strict";n.d(t,{H:()=>s,f:()=>i});var r=n(6550),a=n(7462),o=n(7294);function i(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var a=e.path?(0,r.LX)(t,e):n.length?n[n.length-1].match:r.F0.computeRootMatch(t);return a&&(n.push({route:e,match:a}),e.routes&&i(e.routes,t,n)),a})),n}function s(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?o.createElement(r.rs,n,e.map((function(e,n){return o.createElement(r.AW,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,a.Z)({},n,{},t,{route:e})):o.createElement(e.component,(0,a.Z)({},n,t,{route:e}))}})}))):null}},3727:(e,t,n)=>{"use strict";n.d(t,{OL:()=>y,VK:()=>u,rU:()=>g});var r=n(6550),a=n(5068),o=n(7294),i=n(9318),s=n(7462),l=n(3366),c=n(8776),u=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(t=e.call.apply(e,[this].concat(r))||this).history=(0,i.lX)(t.props),t}return(0,a.Z)(t,e),t.prototype.render=function(){return o.createElement(r.F0,{history:this.history,children:this.props.children})},t}(o.Component);o.Component;var d=function(e,t){return"function"==typeof e?e(t):e},p=function(e,t){return"string"==typeof e?(0,i.ob)(e,null,null,t):e},f=function(e){return e},m=o.forwardRef;void 0===m&&(m=f);var h=m((function(e,t){var n=e.innerRef,r=e.navigate,a=e.onClick,i=(0,l.Z)(e,["innerRef","navigate","onClick"]),c=i.target,u=(0,s.Z)({},i,{onClick:function(e){try{a&&a(e)}catch(t){throw e.preventDefault(),t}e.defaultPrevented||0!==e.button||c&&"_self"!==c||function(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}(e)||(e.preventDefault(),r())}});return u.ref=f!==m&&t||n,o.createElement("a",u)}));var g=m((function(e,t){var n=e.component,a=void 0===n?h:n,u=e.replace,g=e.to,b=e.innerRef,v=(0,l.Z)(e,["component","replace","to","innerRef"]);return o.createElement(r.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=e.history,r=p(d(g,e.location),e.location),l=r?n.createHref(r):"",h=(0,s.Z)({},v,{href:l,navigate:function(){var t=d(g,e.location),r=(0,i.Ep)(e.location)===(0,i.Ep)(p(t));(u||r?n.replace:n.push)(t)}});return f!==m?h.ref=t||b:h.innerRef=b,o.createElement(a,h)}))})),b=function(e){return e},v=o.forwardRef;void 0===v&&(v=b);var y=v((function(e,t){var n=e["aria-current"],a=void 0===n?"page":n,i=e.activeClassName,u=void 0===i?"active":i,f=e.activeStyle,m=e.className,h=e.exact,y=e.isActive,x=e.location,w=e.sensitive,k=e.strict,S=e.style,_=e.to,E=e.innerRef,C=(0,l.Z)(e,["aria-current","activeClassName","activeStyle","className","exact","isActive","location","sensitive","strict","style","to","innerRef"]);return o.createElement(r.s6.Consumer,null,(function(e){e||(0,c.Z)(!1);var n=x||e.location,i=p(d(_,n),n),l=i.pathname,T=l&&l.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1"),j=T?(0,r.LX)(n.pathname,{path:T,exact:h,sensitive:w,strict:k}):null,A=!!(y?y(j,n):j),L="function"==typeof m?m(A):m,R="function"==typeof S?S(A):S;A&&(L=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.filter((function(e){return e})).join(" ")}(L,u),R=(0,s.Z)({},R,f));var N=(0,s.Z)({"aria-current":A&&a||null,className:L,style:R,to:i},C);return b!==v?N.ref=t||E:N.innerRef=E,o.createElement(g,N)}))}))},6550:(e,t,n)=>{"use strict";n.d(t,{AW:()=>_,F0:()=>y,LX:()=>S,TH:()=>P,k6:()=>N,rs:()=>L,s6:()=>v});var r=n(5068),a=n(7294),o=n(5697),i=n.n(o),s=n(9318),l=n(8776),c=n(7462),u=n(9658),d=n.n(u),p=(n(9864),n(3366)),f=(n(8679),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};var h=a.createContext||function(e,t){var n,o,s="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",l=function(e){function n(){for(var t,n,r,a=arguments.length,o=new Array(a),i=0;i<a;i++)o[i]=arguments[i];return(t=e.call.apply(e,[this].concat(o))||this).emitter=(n=t.props.value,r=[],{on:function(e){r.push(e)},off:function(e){r=r.filter((function(t){return t!==e}))},get:function(){return n},set:function(e,t){n=e,r.forEach((function(e){return e(n,t)}))}}),t}(0,r.Z)(n,e);var a=n.prototype;return a.getChildContext=function(){var e;return(e={})[s]=this.emitter,e},a.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,a=e.value;((o=r)===(i=a)?0!==o||1/o==1/i:o!=o&&i!=i)?n=0:(n="function"==typeof t?t(r,a):f,0!==(n|=0)&&this.emitter.set(e.value,n))}var o,i},a.render=function(){return this.props.children},n}(a.Component);l.childContextTypes=((n={})[s]=i().object.isRequired,n);var c=function(t){function n(){for(var e,n=arguments.length,r=new Array(n),a=0;a<n;a++)r[a]=arguments[a];return(e=t.call.apply(t,[this].concat(r))||this).observedBits=void 0,e.state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}(0,r.Z)(n,t);var a=n.prototype;return a.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?f:t},a.componentDidMount=function(){this.context[s]&&this.context[s].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?f:e},a.componentWillUnmount=function(){this.context[s]&&this.context[s].off(this.onUpdate)},a.getValue=function(){return this.context[s]?this.context[s].get():e},a.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(a.Component);return c.contextTypes=((o={})[s]=i().object,o),{Provider:l,Consumer:c}},g=function(e){var t=h();return t.displayName=e,t},b=g("Router-History"),v=g("Router"),y=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._pendingLocation=e}))),n}(0,r.Z)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){var e=this;this._isMounted=!0,this.unlisten&&this.unlisten(),this.props.staticContext||(this.unlisten=this.props.history.listen((function(t){e._isMounted&&e.setState({location:t})}))),this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&(this.unlisten(),this._isMounted=!1,this._pendingLocation=null)},n.render=function(){return a.createElement(v.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},a.createElement(b.Provider,{children:this.props.children||null,value:this.props.history}))},t}(a.Component);a.Component;a.Component;var x={},w=1e4,k=0;function S(e,t){void 0===t&&(t={}),("string"==typeof t||Array.isArray(t))&&(t={path:t});var n=t,r=n.path,a=n.exact,o=void 0!==a&&a,i=n.strict,s=void 0!==i&&i,l=n.sensitive,c=void 0!==l&&l;return[].concat(r).reduce((function(t,n){if(!n&&""!==n)return null;if(t)return t;var r=function(e,t){var n=""+t.end+t.strict+t.sensitive,r=x[n]||(x[n]={});if(r[e])return r[e];var a=[],o={regexp:d()(e,a,t),keys:a};return k<w&&(r[e]=o,k++),o}(n,{end:o,strict:s,sensitive:c}),a=r.regexp,i=r.keys,l=a.exec(e);if(!l)return null;var u=l[0],p=l.slice(1),f=e===u;return o&&!f?null:{path:n,url:"/"===n&&""===u?"/":u,isExact:f,params:i.reduce((function(e,t,n){return e[t.name]=p[n],e}),{})}}),null)}var _=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(v.Consumer,null,(function(t){t||(0,l.Z)(!1);var n=e.props.location||t.location,r=e.props.computedMatch?e.props.computedMatch:e.props.path?S(n.pathname,e.props):t.match,o=(0,c.Z)({},t,{location:n,match:r}),i=e.props,s=i.children,u=i.component,d=i.render;return Array.isArray(s)&&function(e){return 0===a.Children.count(e)}(s)&&(s=null),a.createElement(v.Provider,{value:o},o.match?s?"function"==typeof s?s(o):s:u?a.createElement(u,o):d?d(o):null:"function"==typeof s?s(o):null)}))},t}(a.Component);function E(e){return"/"===e.charAt(0)?e:"/"+e}function C(e,t){if(!e)return t;var n=E(e);return 0!==t.pathname.indexOf(n)?t:(0,c.Z)({},t,{pathname:t.pathname.substr(n.length)})}function T(e){return"string"==typeof e?e:(0,s.Ep)(e)}function j(e){return function(){(0,l.Z)(!1)}}function A(){}a.Component;var L=function(e){function t(){return e.apply(this,arguments)||this}return(0,r.Z)(t,e),t.prototype.render=function(){var e=this;return a.createElement(v.Consumer,null,(function(t){t||(0,l.Z)(!1);var n,r,o=e.props.location||t.location;return a.Children.forEach(e.props.children,(function(e){if(null==r&&a.isValidElement(e)){n=e;var i=e.props.path||e.props.from;r=i?S(o.pathname,(0,c.Z)({},e.props,{path:i})):t.match}})),r?a.cloneElement(n,{location:o,computedMatch:r}):null}))},t}(a.Component);var R=a.useContext;function N(){return R(b)}function P(){return R(v).location}},9658:(e,t,n)=>{var r=n(5826);e.exports=f,e.exports.parse=o,e.exports.compile=function(e,t){return s(o(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=p;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,s="",u=t&&t.delimiter||"/";null!=(n=a.exec(e));){var d=n[0],p=n[1],f=n.index;if(s+=e.slice(i,f),i=f+d.length,p)s+=p[1];else{var m=e[i],h=n[2],g=n[3],b=n[4],v=n[5],y=n[6],x=n[7];s&&(r.push(s),s="");var w=null!=h&&null!=m&&m!==h,k="+"===y||"*"===y,S="?"===y||"*"===y,_=n[2]||u,E=b||v;r.push({name:g||o++,prefix:h||"",delimiter:_,optional:S,repeat:k,partial:w,asterisk:!!x,pattern:E?c(E):x?".*":"[^"+l(_)+"]+?"})}}return i<e.length&&(s+=e.substr(i)),s&&r.push(s),r}function i(e){return encodeURI(e).replace(/[\/?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function s(e,t){for(var n=new Array(e.length),a=0;a<e.length;a++)"object"==typeof e[a]&&(n[a]=new RegExp("^(?:"+e[a].pattern+")$",d(t)));return function(t,a){for(var o="",s=t||{},l=(a||{}).pretty?i:encodeURIComponent,c=0;c<e.length;c++){var u=e[c];if("string"!=typeof u){var d,p=s[u.name];if(null==p){if(u.optional){u.partial&&(o+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(r(p)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(p)+"`");if(0===p.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var f=0;f<p.length;f++){if(d=l(p[f]),!n[c].test(d))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(d)+"`");o+=(0===f?u.prefix:u.delimiter)+d}}else{if(d=u.asterisk?encodeURI(p).replace(/[?#]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})):l(p),!n[c].test(d))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+d+'"');o+=u.prefix+d}}else o+=u}return o}}function l(e){return e.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function c(e){return e.replace(/([=!:$\/()])/g,"\\$1")}function u(e,t){return e.keys=t,e}function d(e){return e&&e.sensitive?"":"i"}function p(e,t,n){r(t)||(n=t||n,t=[]);for(var a=(n=n||{}).strict,o=!1!==n.end,i="",s=0;s<e.length;s++){var c=e[s];if("string"==typeof c)i+=l(c);else{var p=l(c.prefix),f="(?:"+c.pattern+")";t.push(c),c.repeat&&(f+="(?:"+p+f+")*"),i+=f=c.optional?c.partial?p+"("+f+")?":"(?:"+p+"("+f+"))?":p+"("+f+")"}}var m=l(n.delimiter||"/"),h=i.slice(-m.length)===m;return a||(i=(h?i.slice(0,-m.length):i)+"(?:"+m+"(?=$))?"),i+=o?"$":a&&h?"":"(?="+m+"|$)",u(new RegExp("^"+i,d(n)),t)}function f(e,t,n){return r(t)||(n=t||n,t=[]),n=n||{},e instanceof RegExp?function(e,t){var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return u(e,t)}(e,t):r(e)?function(e,t,n){for(var r=[],a=0;a<e.length;a++)r.push(f(e[a],t,n).source);return u(new RegExp("(?:"+r.join("|")+")",d(n)),t)}(e,t,n):function(e,t,n){return p(o(e,n),t,n)}(e,t,n)}},5251:(e,t,n)=>{"use strict";var r=n(7294),a=Symbol.for("react.element"),o=Symbol.for("react.fragment"),i=Object.prototype.hasOwnProperty,s=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,n){var r,o={},c=null,u=null;for(r in void 0!==n&&(c=""+n),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(u=t.ref),t)i.call(t,r)&&!l.hasOwnProperty(r)&&(o[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===o[r]&&(o[r]=t[r]);return{$$typeof:a,type:e,key:c,ref:u,props:o,_owner:s.current}}t.Fragment=o,t.jsx=c,t.jsxs=c},2408:(e,t)=>{"use strict";var n=Symbol.for("react.element"),r=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),s=Symbol.for("react.provider"),l=Symbol.for("react.context"),c=Symbol.for("react.forward_ref"),u=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),f=Symbol.iterator;var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h=Object.assign,g={};function b(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}function v(){}function y(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}b.prototype.isReactComponent={},b.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},b.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},v.prototype=b.prototype;var x=y.prototype=new v;x.constructor=y,h(x,b.prototype),x.isPureReactComponent=!0;var w=Array.isArray,k=Object.prototype.hasOwnProperty,S={current:null},_={key:!0,ref:!0,__self:!0,__source:!0};function E(e,t,r){var a,o={},i=null,s=null;if(null!=t)for(a in void 0!==t.ref&&(s=t.ref),void 0!==t.key&&(i=""+t.key),t)k.call(t,a)&&!_.hasOwnProperty(a)&&(o[a]=t[a]);var l=arguments.length-2;if(1===l)o.children=r;else if(1<l){for(var c=Array(l),u=0;u<l;u++)c[u]=arguments[u+2];o.children=c}if(e&&e.defaultProps)for(a in l=e.defaultProps)void 0===o[a]&&(o[a]=l[a]);return{$$typeof:n,type:e,key:i,ref:s,props:o,_owner:S.current}}function C(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}var T=/\/+/g;function j(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function A(e,t,a,o,i){var s=typeof e;"undefined"!==s&&"boolean"!==s||(e=null);var l=!1;if(null===e)l=!0;else switch(s){case"string":case"number":l=!0;break;case"object":switch(e.$$typeof){case n:case r:l=!0}}if(l)return i=i(l=e),e=""===o?"."+j(l,0):o,w(i)?(a="",null!=e&&(a=e.replace(T,"$&/")+"/"),A(i,t,a,"",(function(e){return e}))):null!=i&&(C(i)&&(i=function(e,t){return{$$typeof:n,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(i,a+(!i.key||l&&l.key===i.key?"":(""+i.key).replace(T,"$&/")+"/")+e)),t.push(i)),1;if(l=0,o=""===o?".":o+":",w(e))for(var c=0;c<e.length;c++){var u=o+j(s=e[c],c);l+=A(s,t,a,u,i)}else if(u=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=f&&e[f]||e["@@iterator"])?e:null}(e),"function"==typeof u)for(e=u.call(e),c=0;!(s=e.next()).done;)l+=A(s=s.value,t,a,u=o+j(s,c++),i);else if("object"===s)throw t=String(e),Error("Objects are not valid as a React child (found: "+("[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.");return l}function L(e,t,n){if(null==e)return e;var r=[],a=0;return A(e,r,"","",(function(e){return t.call(n,e,a++)})),r}function R(e){if(-1===e._status){var t=e._result;(t=t()).then((function(t){0!==e._status&&-1!==e._status||(e._status=1,e._result=t)}),(function(t){0!==e._status&&-1!==e._status||(e._status=2,e._result=t)})),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var N={current:null},P={transition:null},O={ReactCurrentDispatcher:N,ReactCurrentBatchConfig:P,ReactCurrentOwner:S};t.Children={map:L,forEach:function(e,t,n){L(e,(function(){t.apply(this,arguments)}),n)},count:function(e){var t=0;return L(e,(function(){t++})),t},toArray:function(e){return L(e,(function(e){return e}))||[]},only:function(e){if(!C(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},t.Component=b,t.Fragment=a,t.Profiler=i,t.PureComponent=y,t.StrictMode=o,t.Suspense=u,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=O,t.cloneElement=function(e,t,r){if(null==e)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var a=h({},e.props),o=e.key,i=e.ref,s=e._owner;if(null!=t){if(void 0!==t.ref&&(i=t.ref,s=S.current),void 0!==t.key&&(o=""+t.key),e.type&&e.type.defaultProps)var l=e.type.defaultProps;for(c in t)k.call(t,c)&&!_.hasOwnProperty(c)&&(a[c]=void 0===t[c]&&void 0!==l?l[c]:t[c])}var c=arguments.length-2;if(1===c)a.children=r;else if(1<c){l=Array(c);for(var u=0;u<c;u++)l[u]=arguments[u+2];a.children=l}return{$$typeof:n,type:e.type,key:o,ref:i,props:a,_owner:s}},t.createContext=function(e){return(e={$$typeof:l,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null}).Provider={$$typeof:s,_context:e},e.Consumer=e},t.createElement=E,t.createFactory=function(e){var t=E.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:c,render:e}},t.isValidElement=C,t.lazy=function(e){return{$$typeof:p,_payload:{_status:-1,_result:e},_init:R}},t.memo=function(e,t){return{$$typeof:d,type:e,compare:void 0===t?null:t}},t.startTransition=function(e){var t=P.transition;P.transition={};try{e()}finally{P.transition=t}},t.unstable_act=function(){throw Error("act(...) is not supported in production builds of React.")},t.useCallback=function(e,t){return N.current.useCallback(e,t)},t.useContext=function(e){return N.current.useContext(e)},t.useDebugValue=function(){},t.useDeferredValue=function(e){return N.current.useDeferredValue(e)},t.useEffect=function(e,t){return N.current.useEffect(e,t)},t.useId=function(){return N.current.useId()},t.useImperativeHandle=function(e,t,n){return N.current.useImperativeHandle(e,t,n)},t.useInsertionEffect=function(e,t){return N.current.useInsertionEffect(e,t)},t.useLayoutEffect=function(e,t){return N.current.useLayoutEffect(e,t)},t.useMemo=function(e,t){return N.current.useMemo(e,t)},t.useReducer=function(e,t,n){return N.current.useReducer(e,t,n)},t.useRef=function(e){return N.current.useRef(e)},t.useState=function(e){return N.current.useState(e)},t.useSyncExternalStore=function(e,t,n){return N.current.useSyncExternalStore(e,t,n)},t.useTransition=function(){return N.current.useTransition()},t.version="18.2.0"},7294:(e,t,n)=>{"use strict";e.exports=n(2408)},5893:(e,t,n)=>{"use strict";e.exports=n(5251)},53:(e,t)=>{"use strict";function n(e,t){var n=e.length;e.push(t);e:for(;0<n;){var r=n-1>>>1,a=e[r];if(!(0<o(a,t)))break e;e[r]=t,e[n]=a,n=r}}function r(e){return 0===e.length?null:e[0]}function a(e){if(0===e.length)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,a=e.length,i=a>>>1;r<i;){var s=2*(r+1)-1,l=e[s],c=s+1,u=e[c];if(0>o(l,n))c<a&&0>o(u,l)?(e[r]=u,e[c]=n,r=c):(e[r]=l,e[s]=n,r=s);else{if(!(c<a&&0>o(u,n)))break e;e[r]=u,e[c]=n,r=c}}}return t}function o(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;t.unstable_now=function(){return i.now()}}else{var s=Date,l=s.now();t.unstable_now=function(){return s.now()-l}}var c=[],u=[],d=1,p=null,f=3,m=!1,h=!1,g=!1,b="function"==typeof setTimeout?setTimeout:null,v="function"==typeof clearTimeout?clearTimeout:null,y="undefined"!=typeof setImmediate?setImmediate:null;function x(e){for(var t=r(u);null!==t;){if(null===t.callback)a(u);else{if(!(t.startTime<=e))break;a(u),t.sortIndex=t.expirationTime,n(c,t)}t=r(u)}}function w(e){if(g=!1,x(e),!h)if(null!==r(c))h=!0,P(k);else{var t=r(u);null!==t&&O(w,t.startTime-e)}}function k(e,n){h=!1,g&&(g=!1,v(C),C=-1),m=!0;var o=f;try{for(x(n),p=r(c);null!==p&&(!(p.expirationTime>n)||e&&!A());){var i=p.callback;if("function"==typeof i){p.callback=null,f=p.priorityLevel;var s=i(p.expirationTime<=n);n=t.unstable_now(),"function"==typeof s?p.callback=s:p===r(c)&&a(c),x(n)}else a(c);p=r(c)}if(null!==p)var l=!0;else{var d=r(u);null!==d&&O(w,d.startTime-n),l=!1}return l}finally{p=null,f=o,m=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var S,_=!1,E=null,C=-1,T=5,j=-1;function A(){return!(t.unstable_now()-j<T)}function L(){if(null!==E){var e=t.unstable_now();j=e;var n=!0;try{n=E(!0,e)}finally{n?S():(_=!1,E=null)}}else _=!1}if("function"==typeof y)S=function(){y(L)};else if("undefined"!=typeof MessageChannel){var R=new MessageChannel,N=R.port2;R.port1.onmessage=L,S=function(){N.postMessage(null)}}else S=function(){b(L,0)};function P(e){E=e,_||(_=!0,S())}function O(e,n){C=b((function(){e(t.unstable_now())}),n)}t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){h||m||(h=!0,P(k))},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):T=0<e?Math.floor(1e3/e):5},t.unstable_getCurrentPriorityLevel=function(){return f},t.unstable_getFirstCallbackNode=function(){return r(c)},t.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=function(){},t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},t.unstable_scheduleCallback=function(e,a,o){var i=t.unstable_now();switch("object"==typeof o&&null!==o?o="number"==typeof(o=o.delay)&&0<o?i+o:i:o=i,e){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return e={id:d++,callback:a,priorityLevel:e,startTime:o,expirationTime:s=o+s,sortIndex:-1},o>i?(e.sortIndex=o,n(u,e),null===r(c)&&e===r(u)&&(g?(v(C),C=-1):g=!0,O(w,o-i))):(e.sortIndex=s,n(c,e),h||m||(h=!0,P(k))),e},t.unstable_shouldYield=A,t.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}},3840:(e,t,n)=>{"use strict";e.exports=n(53)},6774:e=>{e.exports=function(e,t,n,r){var a=n?n.call(r,e,t):void 0;if(void 0!==a)return!!a;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var o=Object.keys(e),i=Object.keys(t);if(o.length!==i.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),l=0;l<o.length;l++){var c=o[l];if(!s(c))return!1;var u=e[c],d=t[c];if(!1===(a=n?n.call(r,u,d,c):void 0)||void 0===a&&u!==d)return!1}return!0}},6809:(e,t,n)=>{"use strict";n.d(t,{default:()=>r});const r={title:"Eraser Docs",url:"https://eraser-dev.github.io",baseUrl:"/eraser/docs/",onBrokenLinks:"warn",onBrokenMarkdownLinks:"warn",favicon:"img/favicon.ico",trailingSlash:!1,organizationName:"eraser-dev",projectName:"Eraser",deploymentBranch:"gh-pages",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["classic",{docs:{sidebarPath:"/home/runner/work/eraser/eraser/docs/sidebars.js",routeBasePath:"/"},blog:!1,theme:{customCss:"/home/runner/work/eraser/eraser/docs/src/css/custom.css"},gtag:{trackingID:"G-QV5PNCJ560",anonymizeIP:!0}}]],themeConfig:{navbar:{title:"Eraser",logo:{alt:"Eraser Logo",src:"img/eraser.svg"},items:[{type:"docsVersionDropdown",position:"right",dropdownItemsBefore:[],dropdownItemsAfter:[]},{href:"https://github.com/eraser-dev/eraser",position:"right",className:"header-github-link","aria-label":"GitHub repository"}],hideOnScroll:!1},footer:{style:"dark",copyright:'Copyright \xa9 2024 Linux Foundation. The Linux Foundation\xae (TLF) has registered trademarks and uses trademarks. For a list of TLF trademarks, see <a href="https://www.linuxfoundation.org/trademark-usage/">Trademark Usage</a>.',links:[]},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},additionalLanguages:[],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},algolia:{appId:"X8MU4GEC0G",apiKey:"aaca7901c07e616a7ec2e1e1f9670809",indexName:"eraser",contextualSearch:!0,searchParameters:{},searchPagePath:"search"},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!0},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,onBrokenAnchors:"warn",onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},plugins:[],themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],tagline:"",titleDelimiter:"|",noIndex:!1,markdown:{format:"mdx",mermaid:!1,mdx1Compat:{comments:!0,admonitions:!0,headingIds:!0}}}},7462:(e,t,n)=>{"use strict";function r(){return r=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},r.apply(this,arguments)}n.d(t,{Z:()=>r})},5068:(e,t,n)=>{"use strict";function r(e,t){return r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},r(e,t)}function a(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>a})},3366:(e,t,n)=>{"use strict";function r(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}n.d(t,{Z:()=>r})},512:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(n=r(e[t]))&&(a&&(a+=" "),a+=n)}else for(n in e)e[n]&&(a&&(a+=" "),a+=n);return a}n.d(t,{Z:()=>a});const a=function(){for(var e,t,n=0,a="",o=arguments.length;n<o;n++)(e=arguments[n])&&(t=r(e))&&(a&&(a+=" "),a+=t);return a}},2573:(e,t,n)=>{"use strict";n.d(t,{p1:()=>T,y$:()=>ee});var r,a,o,i,s,l,c,u=n(7294),d=n(512),p=Object.create,f=Object.defineProperty,m=Object.defineProperties,h=Object.getOwnPropertyDescriptor,g=Object.getOwnPropertyDescriptors,b=Object.getOwnPropertyNames,v=Object.getOwnPropertySymbols,y=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty,w=Object.prototype.propertyIsEnumerable,k=(e,t,n)=>t in e?f(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,S=(e,t)=>{for(var n in t||(t={}))x.call(t,n)&&k(e,n,t[n]);if(v)for(var n of v(t))w.call(t,n)&&k(e,n,t[n]);return e},_=(e,t)=>m(e,g(t)),E=(e,t)=>{var n={};for(var r in e)x.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&v)for(var r of v(e))t.indexOf(r)<0&&w.call(e,r)&&(n[r]=e[r]);return n},C=(r={"../../node_modules/.pnpm/prismjs@1.29.0_patch_hash=vrxx3pzkik6jpmgpayxfjunetu/node_modules/prismjs/prism.js"(e,t){var n=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(t,n){var a,o;switch(n=n||{},r.util.type(t)){case"Object":if(o=r.util.objId(t),n[o])return n[o];for(var i in a={},n[o]=a,t)t.hasOwnProperty(i)&&(a[i]=e(t[i],n));return a;case"Array":return o=r.util.objId(t),n[o]?n[o]:(a=[],n[o]=a,t.forEach((function(t,r){a[r]=e(t,n)})),a);default:return t}},getLanguage:function(t){for(;t;){var n=e.exec(t.className);if(n)return n[1].toLowerCase();t=t.parentElement}return"none"},setLanguage:function(t,n){t.className=t.className.replace(RegExp(e,"gi"),""),t.classList.add("language-"+n)},isActive:function(e,t,n){for(var r="no-"+t;e;){var a=e.classList;if(a.contains(t))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!n}},languages:{plain:n,plaintext:n,text:n,txt:n,extend:function(e,t){var n=r.util.clone(r.languages[e]);for(var a in t)n[a]=t[a];return n},insertBefore:function(e,t,n,a){var o=(a=a||r.languages)[e],i={};for(var s in o)if(o.hasOwnProperty(s)){if(s==t)for(var l in n)n.hasOwnProperty(l)&&(i[l]=n[l]);n.hasOwnProperty(s)||(i[s]=o[s])}var c=a[e];return a[e]=i,r.languages.DFS(r.languages,(function(t,n){n===c&&t!=e&&(this[t]=i)})),i},DFS:function e(t,n,a,o){o=o||{};var i=r.util.objId;for(var s in t)if(t.hasOwnProperty(s)){n.call(t,s,t[s],a||s);var l=t[s],c=r.util.type(l);"Object"!==c||o[i(l)]?"Array"!==c||o[i(l)]||(o[i(l)]=!0,e(l,n,s,o)):(o[i(l)]=!0,e(l,n,null,o))}}},plugins:{},highlight:function(e,t,n){var o={code:e,grammar:t,language:n};if(r.hooks.run("before-tokenize",o),!o.grammar)throw new Error('The language "'+o.language+'" has no grammar.');return o.tokens=r.tokenize(o.code,o.grammar),r.hooks.run("after-tokenize",o),a.stringify(r.util.encode(o.tokens),o.language)},tokenize:function(e,t){var n=t.rest;if(n){for(var r in n)t[r]=n[r];delete t.rest}var a=new s;return l(a,a.head,e),i(e,a,t,a.head,0),function(e){for(var t=[],n=e.head.next;n!==e.tail;)t.push(n.value),n=n.next;return t}(a)},hooks:{all:{},add:function(e,t){var n=r.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=r.hooks.all[e];if(n&&n.length)for(var a,o=0;a=n[o++];)a(t)}},Token:a};function a(e,t,n,r){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length}function o(e,t,n,r){e.lastIndex=t;var a=e.exec(n);if(a&&r&&a[1]){var o=a[1].length;a.index+=o,a[0]=a[0].slice(o)}return a}function i(e,t,n,s,u,d){for(var p in n)if(n.hasOwnProperty(p)&&n[p]){var f=n[p];f=Array.isArray(f)?f:[f];for(var m=0;m<f.length;++m){if(d&&d.cause==p+","+m)return;var h=f[m],g=h.inside,b=!!h.lookbehind,v=!!h.greedy,y=h.alias;if(v&&!h.pattern.global){var x=h.pattern.toString().match(/[imsuy]*$/)[0];h.pattern=RegExp(h.pattern.source,x+"g")}for(var w=h.pattern||h,k=s.next,S=u;k!==t.tail&&!(d&&S>=d.reach);S+=k.value.length,k=k.next){var _=k.value;if(t.length>e.length)return;if(!(_ instanceof a)){var E,C=1;if(v){if(!(E=o(w,S,e,b))||E.index>=e.length)break;var T=E.index,j=E.index+E[0].length,A=S;for(A+=k.value.length;T>=A;)A+=(k=k.next).value.length;if(S=A-=k.value.length,k.value instanceof a)continue;for(var L=k;L!==t.tail&&(A<j||"string"==typeof L.value);L=L.next)C++,A+=L.value.length;C--,_=e.slice(S,A),E.index-=S}else if(!(E=o(w,0,_,b)))continue;T=E.index;var R=E[0],N=_.slice(0,T),P=_.slice(T+R.length),O=S+_.length;d&&O>d.reach&&(d.reach=O);var I=k.prev;if(N&&(I=l(t,I,N),S+=N.length),c(t,I,C),k=l(t,I,new a(p,g?r.tokenize(R,g):R,y,R)),P&&l(t,k,P),C>1){var D={cause:p+","+m,reach:O};i(e,t,n,k.prev,S,D),d&&D.reach>d.reach&&(d.reach=D.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function c(e,t,n){for(var r=t.next,a=0;a<n&&r!==e.tail;a++)r=r.next;t.next=r,r.prev=t,e.length-=a}return a.stringify=function e(t,n){if("string"==typeof t)return t;if(Array.isArray(t)){var a="";return t.forEach((function(t){a+=e(t,n)})),a}var o={type:t.type,content:e(t.content,n),tag:"span",classes:["token",t.type],attributes:{},language:n},i=t.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(o.classes,i):o.classes.push(i)),r.hooks.run("wrap",o);var s="";for(var l in o.attributes)s+=" "+l+'="'+(o.attributes[l]||"").replace(/"/g,""")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'"'+s+">"+o.content+"</"+o.tag+">"},r}();t.exports=n,n.default=n}},function(){return a||(0,r[b(r)[0]])((a={exports:{}}).exports,a),a.exports}),T=((e,t,n)=>(n=null!=e?p(y(e)):{},((e,t,n,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let a of b(t))x.call(e,a)||a===n||f(e,a,{get:()=>t[a],enumerable:!(r=h(t,a))||r.enumerable});return e})(!t&&e&&e.__esModule?n:f(n,"default",{value:e,enumerable:!0}),e)))(C());T.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},T.languages.markup.tag.inside["attr-value"].inside.entity=T.languages.markup.entity,T.languages.markup.doctype.inside["internal-subset"].inside=T.languages.markup,T.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(T.languages.markup.tag,"addInlined",{value:function(e,t){var n;(t=((n=((n={})["language-"+t]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:T.languages[t]},n.cdata=/^<!\[CDATA\[|\]\]>$/i,{"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:n}}))["language-"+t]={pattern:/[\s\S]+/,inside:T.languages[t]},{}))[e]={pattern:RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:n},T.languages.insertBefore("markup","cdata",t)}}),Object.defineProperty(T.languages.markup.tag,"addAttribute",{value:function(e,t){T.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:T.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),T.languages.html=T.languages.markup,T.languages.mathml=T.languages.markup,T.languages.svg=T.languages.markup,T.languages.xml=T.languages.extend("markup",{}),T.languages.ssml=T.languages.xml,T.languages.atom=T.languages.xml,T.languages.rss=T.languages.xml,o=T,i={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},l="(?:[^\\\\-]|"+(s=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/).source+")",l=RegExp(l+"-"+l),c={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"},o.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:l,inside:{escape:s,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":i,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:s}},"special-escape":i,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":c}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:s,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|<?[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":c}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}},T.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},T.languages.javascript=T.languages.extend("clike",{"class-name":[T.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),T.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,T.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:T.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:T.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:T.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:T.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:T.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),T.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:T.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),T.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),T.languages.markup&&(T.languages.markup.tag.addInlined("script","javascript"),T.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),T.languages.js=T.languages.javascript,T.languages.actionscript=T.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|dynamic|each|else|extends|final|finally|for|function|get|if|implements|import|in|include|instanceof|interface|internal|is|namespace|native|new|null|override|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|use|var|void|while|with)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<<?|>>?>?|[!=]=?)=?|[~?@]/}),T.languages.actionscript["class-name"].alias="function",delete T.languages.actionscript.parameter,delete T.languages.actionscript["literal-property"],T.languages.markup&&T.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:T.languages.markup}}),function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(T),function(e){var t=e.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(t,"addSupport",{value:function(t,n){(t="string"==typeof t?[t]:t).forEach((function(t){var r=function(e){e.inside||(e.inside={}),e.inside.rest=n},a="doc-comment";if(o=e.languages[t]){var o,i=o[a];if((i=i||(o=e.languages.insertBefore(t,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[a])instanceof RegExp&&(i=o[a]={pattern:i}),Array.isArray(i))for(var s=0,l=i.length;s<l;s++)i[s]instanceof RegExp&&(i[s]={pattern:i[s]}),r(i[s]);else r(i)}}))}}),t.addSupport(["java","javascript","php"],t)}(T),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;(t=(e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+t.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css,e.languages.markup))&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(T),function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,n=(t=(e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+t.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[t,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}}),{pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0}),{pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0});e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,number:n})}(T),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*/.source.replace(/<PLAIN>/g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<value>>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<<prop>>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\s*:\s)/.source.replace(/<<prop>>/g,(function(){return r})).replace(/<<key>>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(T),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/<inner>/g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source,i=(e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~)<inner>)+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n<r;n++){var a,o=t[n];"code"!==o.type?e(o.content):(a=o.content[1],o=o.content[3],a&&o&&"code-language"===a.type&&"code-block"===o.type&&"string"==typeof a.content&&(a=a.content.replace(/\b#/g,"sharp").replace(/\b\+\+/g,"pp"),a="language-"+(a=(/[a-z][\w-]*/i.exec(a)||[""])[0].toLowerCase()),o.alias?"string"==typeof o.alias?o.alias=[o.alias,a]:o.alias.push(a):o.alias=[a]))}}(e.tokens)})),e.hooks.add("wrap",(function(t){if("code-block"===t.type){for(var n="",r=0,a=t.classes.length;r<a;r++){var o=t.classes[r];if(o=/language-(.+)/.exec(o)){n=o[1];break}}var c,u=e.languages[n];u?t.content=e.highlight(t.content.replace(i,"").replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,(function(e,t){var n;return"#"===(t=t.toLowerCase())[0]?(n="x"===t[1]?parseInt(t.slice(2),16):Number(t.slice(1)),l(n)):s[t]||e})),u,n):n&&"none"!==n&&e.plugins.autoloader&&(c="md-"+(new Date).valueOf()+"-"+Math.floor(1e16*Math.random()),t.attributes.id=c,e.plugins.autoloader.loadLanguages(n,(function(){var t=document.getElementById(c);t&&(t.innerHTML=e.highlight(t.textContent,e.languages[n],n))})))}})),RegExp(e.languages.markup.tag.pattern.source,"gi")),s={amp:"&",lt:"<",gt:">",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(T),T.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:T.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},T.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n<t.length;){var r=t[n++];if("keyword"===r.type&&"mutation"===r.content){var a=[];if(d(["definition-mutation","punctuation"])&&"("===u(1).content){n+=2;var o=p(/^\($/,/^\)$/);if(-1===o)continue;for(;n<o;n++){var i=u(0);"variable"===i.type&&(f(i,"variable-input"),a.push(i.content))}n=o+1}if(d(["punctuation","property-query"])&&"{"===u(0).content&&(n++,f(u(0),"property-mutation"),0<a.length)){var s=p(/^\{$/,/^\}$/);if(-1!==s)for(var l=n;l<s;l++){var c=t[l];"variable"===c.type&&0<=a.indexOf(c.content)&&f(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n<e.length;n++){var r=u(n+t);if(!r||r.type!==e[n])return}return 1}function p(e,r){for(var a=1,o=n;o<t.length;o++){var i=t[o],s=i.content;if("punctuation"===i.type&&"string"==typeof s)if(e.test(s))a++;else if(r.test(s)&&0==--a)return o}return-1}function f(e,t){var n=e.alias;n?Array.isArray(n)||(e.alias=n=[n]):e.alias=n=[],n.push(t)}})),T.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(t,n,r){return t={code:t,grammar:n,language:r},e.hooks.run("before-tokenize",t),t.tokens=e.tokenize(t.code,t.grammar),e.hooks.run("after-tokenize",t),t.tokens}function l(t,n,i){var l=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),c=0,u={},d=(l=s(l.map((function(e){if("string"==typeof e)return e;var n,r;for(e=e.content;-1!==t.indexOf((r=c++,n="___"+i.toUpperCase()+"_"+r+"___")););return u[n]=e,n})).join(""),n,i),Object.keys(u));return c=0,function t(n){for(var o=0;o<n.length;o++){if(c>=d.length)return;var i,l,p,f,m,h,g,b=n[o];"string"==typeof b||"string"==typeof b.content?(i=d[c],-1!==(g=(h="string"==typeof b?b:b.content).indexOf(i))&&(++c,l=h.substring(0,g),m=u[i],p=void 0,(f={})["interpolation-punctuation"]=a,3===(f=e.tokenize(m,f)).length&&((p=[1,1]).push.apply(p,s(f[1],e.languages.javascript,"javascript")),f.splice.apply(f,p)),p=new e.Token("interpolation",f,r.alias,m),f=h.substring(g+i.length),m=[],l&&m.push(l),m.push(p),f&&(t(h=[f]),m.push.apply(m,h)),"string"==typeof b?(n.splice.apply(n,[o,1].concat(m)),o+=m.length-1):b.content=m)):(g=b.content,Array.isArray(g)?t(g):t([g]))}}(l),new e.Token(i,l,"language-"+i,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var c={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function u(e){return"string"==typeof e?e:Array.isArray(e)?e.map(u).join(""):u(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in c&&function t(n){for(var r=0,a=n.length;r<a;r++){var o,i,s,c=n[r];"string"!=typeof c&&(o=c.content,Array.isArray(o)?"template-string"===c.type?(c=o[1],3===o.length&&"string"!=typeof c&&"embedded-code"===c.type&&(i=u(c),c=c.alias,c=Array.isArray(c)?c[0]:c,s=e.languages[c])&&(o[1]=l(i,s,c))):t(o):"string"!=typeof o&&t([o]))}}(t.tokens)}))}(T),function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(T),function(e){var t=e.languages.javascript,n=/\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})+\}/.source,r="(@(?:arg|argument|param|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(r+/(?:(?!\s)[$\w\xA0-\uFFFF.])+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(r+/\[(?:(?!\s)[$\w\xA0-\uFFFF.])+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:t,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp(/(@(?:augments|class|extends|interface|memberof!?|template|this|typedef)\s+(?:<TYPE>\s+)?)[A-Z]\w*(?:\.[A-Z]\w*)*/.source.replace(/<TYPE>/g,(function(){return n}))),lookbehind:!0,inside:{punctuation:/\./}},{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{string:t.string,number:t.number,boolean:t.boolean,keyword:e.languages.typescript.keyword,operator:/=>|\.\.\.|[&|?:*]/,punctuation:/[.,;=<>{}()[\]]/}}],example:{pattern:/(@example\s+(?!\s))(?:[^@\s]|\s+(?!\s))+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^([\t ]*(?:\*\s*)?)\S.*$/m,lookbehind:!0,inside:t,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(T),function(e){e.languages.flow=e.languages.extend("javascript",{}),e.languages.insertBefore("flow","keyword",{type:[{pattern:/\b(?:[Bb]oolean|Function|[Nn]umber|[Ss]tring|[Ss]ymbol|any|mixed|null|void)\b/,alias:"class-name"}]}),e.languages.flow["function-variable"].pattern=/(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=\s*(?:function\b|(?:\([^()]*\)(?:\s*:\s*\w+)?|(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/i,delete e.languages.flow.parameter,e.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(e.languages.flow.keyword)||(e.languages.flow.keyword=[e.languages.flow.keyword]),e.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:Class|declare|opaque|type)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:Diff|Enum|Exact|Keys|ObjMap|PropertyType|Record|Shape|Subtype|Supertype|await)\b(?!\$)/,lookbehind:!0})}(T),T.languages.n4js=T.languages.extend("javascript",{keyword:/\b(?:Array|any|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),T.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),T.languages.n4jsd=T.languages.n4js,function(e){function t(e,t){return RegExp(e.replace(/<ID>/g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:<ID>(?:\s*,\s*(?:\*\s*as\s+<ID>|\{[^{}]*\}))?|\*\s*as\s+<ID>|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+<ID>)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?<ID>/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r<n.length;r++){var a=n[r],o=e.languages.javascript[a];a=(o="RegExp"===e.util.type(o)?e.languages.javascript[a]={pattern:o}:o).inside||{};(o.inside=a)["maybe-class-name"]=/^[A-Z][\s\S]*/}}(T),function(e){var t=e.util.clone(e.languages.javascript),n=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,r=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,a=/(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;function o(e,t){return e=e.replace(/<S>/g,(function(){return n})).replace(/<BRACES>/g,(function(){return r})).replace(/<SPREAD>/g,(function(){return a})),RegExp(e,t)}function i(t){for(var n=[],r=0;r<t.length;r++){var a=t[r],o=!1;"string"!=typeof a&&("tag"===a.type&&a.content[0]&&"tag"===a.content[0].type?"</"===a.content[0].content[0].content?0<n.length&&n[n.length-1].tagName===s(a.content[0].content[1])&&n.pop():"/>"!==a.content[a.content.length-1].content&&n.push({tagName:s(a.content[0].content[1]),openedBraces:0}):0<n.length&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:0<n.length&&0<n[n.length-1].openedBraces&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&0<n.length&&0===n[n.length-1].openedBraces&&(o=s(a),r<t.length-1&&("string"==typeof t[r+1]||"plain-text"===t[r+1].type)&&(o+=s(t[r+1]),t.splice(r+1,1)),0<r&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(o=s(t[r-1])+o,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",o,null,o)),a.content&&"string"!=typeof a.content&&i(a.content)}}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(/<SPREAD>/.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=<BRACES>/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var s=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(s).join(""):""};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||i(e.tokens)}))}(T),function(e){var t=e.util.clone(e.languages.typescript);(t=(e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"],e.languages.tsx.tag)).pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+t.pattern.source+")",t.pattern.flags),t.lookbehind=!0}(T),T.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+/(?:elseif|if)\b/.source+"(?:[ \t]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},T.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=T.languages.swift})),function(e){e.languages.kotlin=e.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete e.languages.kotlin["class-name"];var t={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:e.languages.kotlin}};e.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:t},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:t},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete e.languages.kotlin.string,e.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),e.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),e.languages.kt=e.languages.kotlin,e.languages.kts=e.languages.kotlin}(T),T.languages.c=T.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),T.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),T.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},T.languages.c.string],char:T.languages.c.char,comment:T.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:T.languages.c}}}}),T.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete T.languages.c.boolean,T.languages.objectivec=T.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete T.languages.objectivec["class-name"],T.languages.objc=T.languages.objectivec,T.languages.reason=T.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),T.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete T.languages.reason.function,function(e){for(var t=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source,n=0;n<2;n++)t=t.replace(/<self>/g,(function(){return t}));t=t.replace(/<self>/g,(function(){return/[^\s\S]/.source})),e.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+t),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(T),T.languages.go=T.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),T.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete T.languages.go["class-name"],function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(T),T.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},T.languages.python["string-interpolation"].inside.interpolation.inside.rest=T.languages.python,T.languages.py=T.languages.python;((e,t)=>{for(var n in t)f(e,n,{get:t[n],enumerable:!0})})({},{dracula:()=>j,duotoneDark:()=>A,duotoneLight:()=>L,github:()=>R,jettwaveDark:()=>H,jettwaveLight:()=>Z,nightOwl:()=>N,nightOwlLight:()=>P,oceanicNext:()=>D,okaidia:()=>M,oneDark:()=>G,oneLight:()=>V,palenight:()=>F,shadesOfPurple:()=>z,synthwave84:()=>B,ultramin:()=>$,vsDark:()=>U,vsLight:()=>q});var j={plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]},A={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},L={plain:{backgroundColor:"#faf8f5",color:"#728fcb"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#b6ad9a"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#063289"}},{types:["property","function"],style:{color:"#b29762"}},{types:["tag-id","selector","atrule-id"],style:{color:"#2d2006"}},{types:["attr-name"],style:{color:"#896724"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","atrule"],style:{color:"#728fcb"}},{types:["placeholder","variable"],style:{color:"#93abdc"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#896724"}}]},R={plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},N={plain:{color:"#d6deeb",backgroundColor:"#011627"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(99, 119, 119)",fontStyle:"italic"}},{types:["string","url"],style:{color:"rgb(173, 219, 103)"}},{types:["variable"],style:{color:"rgb(214, 222, 235)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation"],style:{color:"rgb(199, 146, 234)"}},{types:["selector","doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(255, 203, 139)"}},{types:["tag","operator","keyword"],style:{color:"rgb(127, 219, 202)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["property"],style:{color:"rgb(128, 203, 196)"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}}]},P={plain:{color:"#403f53",backgroundColor:"#FBFBFB"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(72, 118, 214)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(152, 159, 177)",fontStyle:"italic"}},{types:["string","builtin","char","constant","url"],style:{color:"rgb(72, 118, 214)"}},{types:["variable"],style:{color:"rgb(201, 103, 101)"}},{types:["number"],style:{color:"rgb(170, 9, 130)"}},{types:["punctuation"],style:{color:"rgb(153, 76, 195)"}},{types:["function","selector","doctype"],style:{color:"rgb(153, 76, 195)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(17, 17, 17)"}},{types:["tag"],style:{color:"rgb(153, 76, 195)"}},{types:["operator","property","keyword","namespace"],style:{color:"rgb(12, 150, 155)"}},{types:["boolean"],style:{color:"rgb(188, 84, 84)"}}]},O="#c5a5c5",I="#8dc891",D={plain:{backgroundColor:"#282c34",color:"#ffffff"},styles:[{types:["attr-name"],style:{color:O}},{types:["attr-value"],style:{color:I}},{types:["comment","block-comment","prolog","doctype","cdata","shebang"],style:{color:"#999999"}},{types:["property","number","function-name","constant","symbol","deleted"],style:{color:"#5a9bcf"}},{types:["boolean"],style:{color:"#ff8b50"}},{types:["tag"],style:{color:"#fc929e"}},{types:["string"],style:{color:I}},{types:["punctuation"],style:{color:I}},{types:["selector","char","builtin","inserted"],style:{color:"#D8DEE9"}},{types:["function"],style:{color:"#79b6f2"}},{types:["operator","entity","url","variable"],style:{color:"#d7deea"}},{types:["keyword"],style:{color:O}},{types:["atrule","class-name"],style:{color:"#FAC863"}},{types:["important"],style:{fontWeight:"400"}},{types:["bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}}]},M={plain:{color:"#f8f8f2",backgroundColor:"#272822"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"#f92672",fontStyle:"italic"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)",fontStyle:"italic"}},{types:["comment"],style:{color:"#8292a2",fontStyle:"italic"}},{types:["string","url"],style:{color:"#a6e22e"}},{types:["variable"],style:{color:"#f8f8f2"}},{types:["number"],style:{color:"#ae81ff"}},{types:["builtin","char","constant","function","class-name"],style:{color:"#e6db74"}},{types:["punctuation"],style:{color:"#f8f8f2"}},{types:["selector","doctype"],style:{color:"#a6e22e",fontStyle:"italic"}},{types:["tag","operator","keyword"],style:{color:"#66d9ef"}},{types:["boolean"],style:{color:"#ae81ff"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)",opacity:.7}},{types:["tag","property"],style:{color:"#f92672"}},{types:["attr-name"],style:{color:"#a6e22e !important"}},{types:["doctype"],style:{color:"#8292a2"}},{types:["rule"],style:{color:"#e6db74"}}]},F={plain:{color:"#bfc7d5",backgroundColor:"#292d3e"},styles:[{types:["comment"],style:{color:"rgb(105, 112, 152)",fontStyle:"italic"}},{types:["string","inserted"],style:{color:"rgb(195, 232, 141)"}},{types:["number"],style:{color:"rgb(247, 140, 108)"}},{types:["builtin","char","constant","function"],style:{color:"rgb(130, 170, 255)"}},{types:["punctuation","selector"],style:{color:"rgb(199, 146, 234)"}},{types:["variable"],style:{color:"rgb(191, 199, 213)"}},{types:["class-name","attr-name"],style:{color:"rgb(255, 203, 107)"}},{types:["tag","deleted"],style:{color:"rgb(255, 85, 114)"}},{types:["operator"],style:{color:"rgb(137, 221, 255)"}},{types:["boolean"],style:{color:"rgb(255, 88, 116)"}},{types:["keyword"],style:{fontStyle:"italic"}},{types:["doctype"],style:{color:"rgb(199, 146, 234)",fontStyle:"italic"}},{types:["namespace"],style:{color:"rgb(178, 204, 214)"}},{types:["url"],style:{color:"rgb(221, 221, 221)"}}]},z={plain:{color:"#9EFEFF",backgroundColor:"#2D2A55"},styles:[{types:["changed"],style:{color:"rgb(255, 238, 128)"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)"}},{types:["inserted"],style:{color:"rgb(173, 219, 103)"}},{types:["comment"],style:{color:"rgb(179, 98, 255)",fontStyle:"italic"}},{types:["punctuation"],style:{color:"rgb(255, 255, 255)"}},{types:["constant"],style:{color:"rgb(255, 98, 140)"}},{types:["string","url"],style:{color:"rgb(165, 255, 144)"}},{types:["variable"],style:{color:"rgb(255, 238, 128)"}},{types:["number","boolean"],style:{color:"rgb(255, 98, 140)"}},{types:["attr-name"],style:{color:"rgb(255, 180, 84)"}},{types:["keyword","operator","property","namespace","tag","selector","doctype"],style:{color:"rgb(255, 157, 0)"}},{types:["builtin","char","constant","function","class-name"],style:{color:"rgb(250, 208, 0)"}}]},B={plain:{backgroundColor:"linear-gradient(to bottom, #2a2139 75%, #34294f)",backgroundImage:"#34294f",color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"},styles:[{types:["comment","block-comment","prolog","doctype","cdata"],style:{color:"#495495",fontStyle:"italic"}},{types:["punctuation"],style:{color:"#ccc"}},{types:["tag","attr-name","namespace","number","unit","hexcode","deleted"],style:{color:"#e2777a"}},{types:["property","selector"],style:{color:"#72f1b8",textShadow:"0 0 2px #100c0f, 0 0 10px #257c5575, 0 0 35px #21272475"}},{types:["function-name"],style:{color:"#6196cc"}},{types:["boolean","selector-id","function"],style:{color:"#fdfdfd",textShadow:"0 0 2px #001716, 0 0 3px #03edf975, 0 0 5px #03edf975, 0 0 8px #03edf975"}},{types:["class-name","maybe-class-name","builtin"],style:{color:"#fff5f6",textShadow:"0 0 2px #000, 0 0 10px #fc1f2c75, 0 0 5px #fc1f2c75, 0 0 25px #fc1f2c75"}},{types:["constant","symbol"],style:{color:"#f92aad",textShadow:"0 0 2px #100c0f, 0 0 5px #dc078e33, 0 0 10px #fff3"}},{types:["important","atrule","keyword","selector-class"],style:{color:"#f4eee4",textShadow:"0 0 2px #393a33, 0 0 8px #f39f0575, 0 0 2px #f39f0575"}},{types:["string","char","attr-value","regex","variable"],style:{color:"#f87c32"}},{types:["parameter"],style:{fontStyle:"italic"}},{types:["entity","url"],style:{color:"#67cdcc"}},{types:["operator"],style:{color:"ffffffee"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["entity"],style:{cursor:"help"}},{types:["inserted"],style:{color:"green"}}]},$={plain:{color:"#282a2e",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(197, 200, 198)"}},{types:["string","number","builtin","variable"],style:{color:"rgb(150, 152, 150)"}},{types:["class-name","function","tag","attr-name"],style:{color:"rgb(40, 42, 46)"}}]},U={plain:{color:"#9CDCFE",backgroundColor:"#1E1E1E"},styles:[{types:["prolog"],style:{color:"rgb(0, 0, 128)"}},{types:["comment"],style:{color:"rgb(106, 153, 85)"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"rgb(86, 156, 214)"}},{types:["number","inserted"],style:{color:"rgb(181, 206, 168)"}},{types:["constant"],style:{color:"rgb(100, 102, 149)"}},{types:["attr-name","variable"],style:{color:"rgb(156, 220, 254)"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"rgb(206, 145, 120)"}},{types:["selector"],style:{color:"rgb(215, 186, 125)"}},{types:["tag"],style:{color:"rgb(78, 201, 176)"}},{types:["tag"],languages:["markup"],style:{color:"rgb(86, 156, 214)"}},{types:["punctuation","operator"],style:{color:"rgb(212, 212, 212)"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"rgb(220, 220, 170)"}},{types:["class-name"],style:{color:"rgb(78, 201, 176)"}},{types:["char"],style:{color:"rgb(209, 105, 105)"}}]},q={plain:{color:"#000000",backgroundColor:"#ffffff"},styles:[{types:["comment"],style:{color:"rgb(0, 128, 0)"}},{types:["builtin"],style:{color:"rgb(0, 112, 193)"}},{types:["number","variable","inserted"],style:{color:"rgb(9, 134, 88)"}},{types:["operator"],style:{color:"rgb(0, 0, 0)"}},{types:["constant","char"],style:{color:"rgb(129, 31, 63)"}},{types:["tag"],style:{color:"rgb(128, 0, 0)"}},{types:["attr-name"],style:{color:"rgb(255, 0, 0)"}},{types:["deleted","string"],style:{color:"rgb(163, 21, 21)"}},{types:["changed","punctuation"],style:{color:"rgb(4, 81, 165)"}},{types:["function","keyword"],style:{color:"rgb(0, 0, 255)"}},{types:["class-name"],style:{color:"rgb(38, 127, 153)"}}]},H={plain:{color:"#f8fafc",backgroundColor:"#011627"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#569CD6"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#f8fafc"}},{types:["attr-name","variable"],style:{color:"#9CDCFE"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#cbd5e1"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#D4D4D4"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#7dd3fc"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},Z={plain:{color:"#0f172a",backgroundColor:"#f1f5f9"},styles:[{types:["prolog"],style:{color:"#000080"}},{types:["comment"],style:{color:"#6A9955"}},{types:["builtin","changed","keyword","interpolation-punctuation"],style:{color:"#0c4a6e"}},{types:["number","inserted"],style:{color:"#B5CEA8"}},{types:["constant"],style:{color:"#0f172a"}},{types:["attr-name","variable"],style:{color:"#0c4a6e"}},{types:["deleted","string","attr-value","template-punctuation"],style:{color:"#64748b"}},{types:["selector"],style:{color:"#D7BA7D"}},{types:["tag"],style:{color:"#0ea5e9"}},{types:["tag"],languages:["markup"],style:{color:"#0ea5e9"}},{types:["punctuation","operator"],style:{color:"#475569"}},{types:["punctuation"],languages:["markup"],style:{color:"#808080"}},{types:["function"],style:{color:"#0e7490"}},{types:["class-name"],style:{color:"#0ea5e9"}},{types:["char"],style:{color:"#D16969"}}]},G={plain:{backgroundColor:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(220, 10%, 40%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(220, 14%, 71%)"}},{types:["attr-name","class-name","maybe-class-name","boolean","constant","number","atrule"],style:{color:"hsl(29, 54%, 61%)"}},{types:["keyword"],style:{color:"hsl(286, 60%, 67%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(355, 65%, 65%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value"],style:{color:"hsl(95, 38%, 62%)"}},{types:["variable","operator","function"],style:{color:"hsl(207, 82%, 66%)"}},{types:["url"],style:{color:"hsl(187, 47%, 55%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(220, 14%, 71%)"}}]},V={plain:{backgroundColor:"hsl(230, 1%, 98%)",color:"hsl(230, 8%, 24%)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(230, 4%, 64%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(230, 8%, 24%)"}},{types:["attr-name","class-name","boolean","constant","number","atrule"],style:{color:"hsl(35, 99%, 36%)"}},{types:["keyword"],style:{color:"hsl(301, 63%, 40%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(5, 74%, 59%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value","punctuation"],style:{color:"hsl(119, 34%, 47%)"}},{types:["variable","operator","function"],style:{color:"hsl(221, 87%, 60%)"}},{types:["url"],style:{color:"hsl(198, 99%, 37%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(230, 8%, 24%)"}}]},W=(e,t)=>{const{plain:n}=e,r=e.styles.reduce(((e,n)=>{const{languages:r,style:a}=n;return r&&!r.includes(t)||n.types.forEach((t=>{const n=S(S({},e[t]),a);e[t]=n})),e}),{});return r.root=n,r.plain=_(S({},n),{backgroundColor:void 0}),r},Q=/\r\n|\r|\n/,K=e=>{0===e.length?e.push({types:["plain"],content:"\n",empty:!0}):1===e.length&&""===e[0].content&&(e[0].content="\n",e[0].empty=!0)},Y=(e,t)=>{const n=e.length;return n>0&&e[n-1]===t?e:e.concat(t)},X=e=>{const t=[[]],n=[e],r=[0],a=[e.length];let o=0,i=0,s=[];const l=[s];for(;i>-1;){for(;(o=r[i]++)<a[i];){let e,c=t[i];const u=n[i][o];if("string"==typeof u?(c=i>0?c:["plain"],e=u):(c=Y(c,u.type),u.alias&&(c=Y(c,u.alias)),e=u.content),"string"!=typeof e){i++,t.push(c),n.push(e),r.push(0),a.push(e.length);continue}const d=e.split(Q),p=d.length;s.push({types:c,content:d[0]});for(let t=1;t<p;t++)K(s),l.push(s=[]),s.push({types:c,content:d[t]})}i--,t.pop(),n.pop(),r.pop(),a.pop()}return K(s),l},J=({children:e,language:t,code:n,theme:r,prism:a})=>{const o=t.toLowerCase(),i=((e,t)=>{const[n,r]=(0,u.useState)(W(t,e)),a=(0,u.useRef)(),o=(0,u.useRef)();return(0,u.useEffect)((()=>{t===a.current&&e===o.current||(a.current=t,o.current=e,r(W(t,e)))}),[e,t]),n})(o,r),s=(e=>(0,u.useCallback)((t=>{var n=t,{className:r,style:a,line:o}=n,i=E(n,["className","style","line"]);const s=_(S({},i),{className:(0,d.Z)("token-line",r)});return"object"==typeof e&&"plain"in e&&(s.style=e.plain),"object"==typeof a&&(s.style=S(S({},s.style||{}),a)),s}),[e]))(i),l=(e=>{const t=(0,u.useCallback)((({types:t,empty:n})=>{if(null!=e)return 1===t.length&&"plain"===t[0]?null!=n?{display:"inline-block"}:void 0:1===t.length&&null!=n?e[t[0]]:Object.assign(null!=n?{display:"inline-block"}:{},...t.map((t=>e[t])))}),[e]);return(0,u.useCallback)((e=>{var n=e,{token:r,className:a,style:o}=n,i=E(n,["token","className","style"]);const s=_(S({},i),{className:(0,d.Z)("token",...r.types,a),children:r.content,style:t(r)});return null!=o&&(s.style=S(S({},s.style||{}),o)),s}),[t])})(i),c=(({prism:e,code:t,grammar:n,language:r})=>{const a=(0,u.useRef)(e);return(0,u.useMemo)((()=>{if(null==n)return X([t]);const e={code:t,grammar:n,language:r,tokens:[]};return a.current.hooks.run("before-tokenize",e),e.tokens=a.current.tokenize(t,n),a.current.hooks.run("after-tokenize",e),X(e.tokens)}),[t,n,r])})({prism:a,language:o,code:n,grammar:a.languages[o]});return e({tokens:c,className:`prism-code language-${o}`,style:null!=i?i.root:{},getLineProps:s,getTokenProps:l})},ee=e=>(0,u.createElement)(J,_(S({},e),{prism:e.prism||T,theme:e.theme||U,code:e.code,language:e.language}))},8776:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=!0,a="Invariant failed";function o(e,t){if(!e){if(r)throw new Error(a);var n="function"==typeof t?t():t,o=n?"".concat(a,": ").concat(n):a;throw new Error(o)}}},7529:e=>{"use strict";e.exports={}},6887:e=>{"use strict";e.exports=JSON.parse('{"/eraser/docs/search-6c2":{"__comp":"1a4e3797","__context":{"plugin":"0a1e161c"}},"/eraser/docs/-8b7":{"__comp":"5e95c892","__context":{"plugin":"621c6848"}},"/eraser/docs/next-271":{"__comp":"a7bd4aaa","version":"935f2afb"},"/eraser/docs/next-ad4":{"__comp":"a94703ab"},"/eraser/docs/next-65e":{"__comp":"17896441","content":"a09c2993"},"/eraser/docs/next/architecture-603":{"__comp":"17896441","content":"5281b7a2"},"/eraser/docs/next/code-of-conduct-9c4":{"__comp":"17896441","content":"dea0f9ea"},"/eraser/docs/next/contributing-9d1":{"__comp":"17896441","content":"4d54d076"},"/eraser/docs/next/custom-scanner-ba1":{"__comp":"17896441","content":"5603335d"},"/eraser/docs/next/customization-240":{"__comp":"17896441","content":"fcff9033"},"/eraser/docs/next/exclusion-3b1":{"__comp":"17896441","content":"7b11c903"},"/eraser/docs/next/faq-764":{"__comp":"17896441","content":"0480b142"},"/eraser/docs/next/installation-fd3":{"__comp":"17896441","content":"3b8c55ea"},"/eraser/docs/next/manual-removal-887":{"__comp":"17896441","content":"4fa03c51"},"/eraser/docs/next/metrics-ca7":{"__comp":"17896441","content":"1dba1ecf"},"/eraser/docs/next/quick-start-a1a":{"__comp":"17896441","content":"72e14192"},"/eraser/docs/next/release-management-0b7":{"__comp":"17896441","content":"1b064146"},"/eraser/docs/next/releasing-bf4":{"__comp":"17896441","content":"7d415946"},"/eraser/docs/next/setup-fa3":{"__comp":"17896441","content":"3847b3ea"},"/eraser/docs/next/trivy-26a":{"__comp":"17896441","content":"fd1ae250"},"/eraser/docs/v0.4.x-43b":{"__comp":"a7bd4aaa","version":"c698fe77"},"/eraser/docs/v0.4.x-7d1":{"__comp":"a94703ab"},"/eraser/docs/v0.4.x-7f6":{"__comp":"17896441","content":"22539a87"},"/eraser/docs/v0.4.x/architecture-029":{"__comp":"17896441","content":"24e97898"},"/eraser/docs/v0.4.x/code-of-conduct-7b8":{"__comp":"17896441","content":"c12dc9fd"},"/eraser/docs/v0.4.x/contributing-7d3":{"__comp":"17896441","content":"48ae5635"},"/eraser/docs/v0.4.x/custom-scanner-c20":{"__comp":"17896441","content":"4eac74de"},"/eraser/docs/v0.4.x/customization-431":{"__comp":"17896441","content":"1c30975d"},"/eraser/docs/v0.4.x/exclusion-1fa":{"__comp":"17896441","content":"d40dbec5"},"/eraser/docs/v0.4.x/faq-86f":{"__comp":"17896441","content":"b9421f89"},"/eraser/docs/v0.4.x/installation-559":{"__comp":"17896441","content":"3fcb412e"},"/eraser/docs/v0.4.x/manual-removal-1d0":{"__comp":"17896441","content":"c108e81c"},"/eraser/docs/v0.4.x/quick-start-e66":{"__comp":"17896441","content":"9e350ec0"},"/eraser/docs/v0.4.x/releasing-058":{"__comp":"17896441","content":"2c8b636f"},"/eraser/docs/v0.4.x/setup-223":{"__comp":"17896441","content":"a932041a"},"/eraser/docs/v0.4.x/trivy-604":{"__comp":"17896441","content":"faa9d310"},"/eraser/docs/v0.5.x-215":{"__comp":"a7bd4aaa","version":"efdb11b6"},"/eraser/docs/v0.5.x-5ca":{"__comp":"a94703ab"},"/eraser/docs/v0.5.x-808":{"__comp":"17896441","content":"c66bbf8a"},"/eraser/docs/v0.5.x/architecture-1a5":{"__comp":"17896441","content":"ec0d5d9e"},"/eraser/docs/v0.5.x/code-of-conduct-0e6":{"__comp":"17896441","content":"11d58a17"},"/eraser/docs/v0.5.x/contributing-324":{"__comp":"17896441","content":"0d9a188d"},"/eraser/docs/v0.5.x/custom-scanner-3a5":{"__comp":"17896441","content":"0390b328"},"/eraser/docs/v0.5.x/customization-8f1":{"__comp":"17896441","content":"12682444"},"/eraser/docs/v0.5.x/exclusion-bee":{"__comp":"17896441","content":"fc618254"},"/eraser/docs/v0.5.x/faq-89b":{"__comp":"17896441","content":"fa2b770f"},"/eraser/docs/v0.5.x/installation-a89":{"__comp":"17896441","content":"c73303db"},"/eraser/docs/v0.5.x/manual-removal-e35":{"__comp":"17896441","content":"20cdecc4"},"/eraser/docs/v0.5.x/quick-start-6f3":{"__comp":"17896441","content":"34f2f592"},"/eraser/docs/v0.5.x/releasing-c0e":{"__comp":"17896441","content":"a683e47f"},"/eraser/docs/v0.5.x/setup-df8":{"__comp":"17896441","content":"8eef7690"},"/eraser/docs/v0.5.x/trivy-2b4":{"__comp":"17896441","content":"bf5c5542"},"/eraser/docs/v1.0.x-2ae":{"__comp":"a7bd4aaa","version":"695a8bbb"},"/eraser/docs/v1.0.x-20b":{"__comp":"a94703ab"},"/eraser/docs/v1.0.x-c03":{"__comp":"17896441","content":"9dbb4f95"},"/eraser/docs/v1.0.x/architecture-0ac":{"__comp":"17896441","content":"bdb5eb86"},"/eraser/docs/v1.0.x/code-of-conduct-ef4":{"__comp":"17896441","content":"dbbf7db4"},"/eraser/docs/v1.0.x/contributing-e7d":{"__comp":"17896441","content":"8cd4fd18"},"/eraser/docs/v1.0.x/custom-scanner-569":{"__comp":"17896441","content":"d7561401"},"/eraser/docs/v1.0.x/customization-85d":{"__comp":"17896441","content":"99ed3086"},"/eraser/docs/v1.0.x/exclusion-3f0":{"__comp":"17896441","content":"62c6dc45"},"/eraser/docs/v1.0.x/faq-8ff":{"__comp":"17896441","content":"4351fb58"},"/eraser/docs/v1.0.x/installation-688":{"__comp":"17896441","content":"72ffabc7"},"/eraser/docs/v1.0.x/manual-removal-8a3":{"__comp":"17896441","content":"8c9fcf50"},"/eraser/docs/v1.0.x/metrics-c54":{"__comp":"17896441","content":"b0fc3de5"},"/eraser/docs/v1.0.x/quick-start-eed":{"__comp":"17896441","content":"9748995c"},"/eraser/docs/v1.0.x/releasing-d7c":{"__comp":"17896441","content":"5af9b662"},"/eraser/docs/v1.0.x/setup-513":{"__comp":"17896441","content":"6ec64a11"},"/eraser/docs/v1.0.x/trivy-5e8":{"__comp":"17896441","content":"6af0c1ea"},"/eraser/docs/v1.1.x-35d":{"__comp":"a7bd4aaa","version":"3e4c86d4"},"/eraser/docs/v1.1.x-8cd":{"__comp":"a94703ab"},"/eraser/docs/v1.1.x-f5e":{"__comp":"17896441","content":"c9ca4745"},"/eraser/docs/v1.1.x/architecture-211":{"__comp":"17896441","content":"70b084fe"},"/eraser/docs/v1.1.x/code-of-conduct-78b":{"__comp":"17896441","content":"8f41530a"},"/eraser/docs/v1.1.x/contributing-1ae":{"__comp":"17896441","content":"bffae3e7"},"/eraser/docs/v1.1.x/custom-scanner-762":{"__comp":"17896441","content":"29ca1a0e"},"/eraser/docs/v1.1.x/customization-9ba":{"__comp":"17896441","content":"dc9281b9"},"/eraser/docs/v1.1.x/exclusion-707":{"__comp":"17896441","content":"e36340b6"},"/eraser/docs/v1.1.x/faq-e2c":{"__comp":"17896441","content":"f2ef54d0"},"/eraser/docs/v1.1.x/installation-a45":{"__comp":"17896441","content":"7c6883b5"},"/eraser/docs/v1.1.x/manual-removal-1e9":{"__comp":"17896441","content":"096837f0"},"/eraser/docs/v1.1.x/metrics-f2a":{"__comp":"17896441","content":"2f4673e5"},"/eraser/docs/v1.1.x/quick-start-9b5":{"__comp":"17896441","content":"db59132a"},"/eraser/docs/v1.1.x/releasing-7ee":{"__comp":"17896441","content":"b70ea2cb"},"/eraser/docs/v1.1.x/setup-ea6":{"__comp":"17896441","content":"59e5a646"},"/eraser/docs/v1.1.x/trivy-fd6":{"__comp":"17896441","content":"e1b2cf59"},"/eraser/docs/v1.2.x-da9":{"__comp":"a7bd4aaa","version":"422308df"},"/eraser/docs/v1.2.x-e65":{"__comp":"a94703ab"},"/eraser/docs/v1.2.x-a9e":{"__comp":"17896441","content":"c4f50fcb"},"/eraser/docs/v1.2.x/architecture-45b":{"__comp":"17896441","content":"bbedbacb"},"/eraser/docs/v1.2.x/code-of-conduct-904":{"__comp":"17896441","content":"a708fa78"},"/eraser/docs/v1.2.x/contributing-80d":{"__comp":"17896441","content":"a8f67d08"},"/eraser/docs/v1.2.x/custom-scanner-fd2":{"__comp":"17896441","content":"7196cdd1"},"/eraser/docs/v1.2.x/customization-a26":{"__comp":"17896441","content":"974203ee"},"/eraser/docs/v1.2.x/exclusion-a73":{"__comp":"17896441","content":"07e6d80c"},"/eraser/docs/v1.2.x/faq-c74":{"__comp":"17896441","content":"3a1ed2bb"},"/eraser/docs/v1.2.x/installation-005":{"__comp":"17896441","content":"6739d7ff"},"/eraser/docs/v1.2.x/manual-removal-4e2":{"__comp":"17896441","content":"ed8448fe"},"/eraser/docs/v1.2.x/metrics-c26":{"__comp":"17896441","content":"e3d8f98f"},"/eraser/docs/v1.2.x/quick-start-901":{"__comp":"17896441","content":"101be56a"},"/eraser/docs/v1.2.x/releasing-e74":{"__comp":"17896441","content":"5bc37772"},"/eraser/docs/v1.2.x/setup-62c":{"__comp":"17896441","content":"0fb10398"},"/eraser/docs/v1.2.x/trivy-617":{"__comp":"17896441","content":"b7730d0d"},"/eraser/docs/-334":{"__comp":"a7bd4aaa","version":"4fb2362d"},"/eraser/docs/-16b":{"__comp":"a94703ab"},"/eraser/docs/architecture-cf6":{"__comp":"17896441","content":"bc344202"},"/eraser/docs/code-of-conduct-ad2":{"__comp":"17896441","content":"6b8e46b3"},"/eraser/docs/contributing-b07":{"__comp":"17896441","content":"bacc1ae0"},"/eraser/docs/custom-scanner-ffa":{"__comp":"17896441","content":"9ff53b5b"},"/eraser/docs/customization-a79":{"__comp":"17896441","content":"5c838b7d"},"/eraser/docs/exclusion-62c":{"__comp":"17896441","content":"9d55bf96"},"/eraser/docs/faq-630":{"__comp":"17896441","content":"30fb9660"},"/eraser/docs/installation-a40":{"__comp":"17896441","content":"7d6336d8"},"/eraser/docs/manual-removal-734":{"__comp":"17896441","content":"bc8dcae3"},"/eraser/docs/metrics-45e":{"__comp":"17896441","content":"93bf47d2"},"/eraser/docs/quick-start-4ca":{"__comp":"17896441","content":"ae417a11"},"/eraser/docs/release-management-50e":{"__comp":"17896441","content":"e7fdf6d9"},"/eraser/docs/releasing-925":{"__comp":"17896441","content":"b7cd4035"},"/eraser/docs/setup-2c2":{"__comp":"17896441","content":"c853dc39"},"/eraser/docs/trivy-86b":{"__comp":"17896441","content":"44b2adf6"},"/eraser/docs/-5aa":{"__comp":"17896441","content":"85c70040"}}')}},e=>{e.O(0,[532],(()=>{return t=7221,e(e.s=t);var t}));e.O()}]); \ No newline at end of file diff --git a/docs/assets/js/main.3fdea3bd.js.LICENSE.txt b/docs/assets/js/main.424bf04c.js.LICENSE.txt similarity index 76% rename from docs/assets/js/main.3fdea3bd.js.LICENSE.txt rename to docs/assets/js/main.424bf04c.js.LICENSE.txt index eb75d69107..91dc894998 100644 --- a/docs/assets/js/main.3fdea3bd.js.LICENSE.txt +++ b/docs/assets/js/main.424bf04c.js.LICENSE.txt @@ -1,15 +1,22 @@ -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ - /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress * @license MIT */ +/*! Bundled license information: + +prismjs/prism.js: + (** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT <https://opensource.org/licenses/MIT> + * @author Lea Verou <https://lea.verou.me> + * @namespace + * @public + *) +*/ + /** * @license React - * use-sync-external-store-shim.production.min.js + * react-dom.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * @@ -18,16 +25,8 @@ object-assign */ /** - * Prism: Lightweight, robust, elegant syntax highlighting - * - * @license MIT <https://opensource.org/licenses/MIT> - * @author Lea Verou <https://lea.verou.me> - * @namespace - * @public - */ - -/** @license React v0.20.2 - * scheduler.production.min.js + * @license React + * react-jsx-runtime.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * @@ -35,8 +34,9 @@ object-assign * LICENSE file in the root directory of this source tree. */ -/** @license React v16.13.1 - * react-is.production.min.js +/** + * @license React + * react.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * @@ -44,8 +44,9 @@ object-assign * LICENSE file in the root directory of this source tree. */ -/** @license React v17.0.2 - * react-dom.production.min.js +/** + * @license React + * scheduler.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * @@ -53,8 +54,8 @@ object-assign * LICENSE file in the root directory of this source tree. */ -/** @license React v17.0.2 - * react.production.min.js +/** @license React v16.13.1 + * react-is.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * diff --git a/docs/assets/js/runtime~main.3e75485d.js b/docs/assets/js/runtime~main.3e75485d.js deleted file mode 100644 index 38dd41cbda..0000000000 --- a/docs/assets/js/runtime~main.3e75485d.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{"use strict";var e,a,f,b,c,d={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={id:e,loaded:!1,exports:{}};return d[e].call(f.exports,f,f.exports,r),f.loaded=!0,f.exports}r.m=d,r.c=t,e=[],r.O=(a,f,b,c)=>{if(!f){var d=1/0;for(i=0;i<e.length;i++){f=e[i][0],b=e[i][1],c=e[i][2];for(var t=!0,o=0;o<f.length;o++)(!1&c||d>=c)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,c<d&&(d=c));if(t){e.splice(i--,1);var n=b();void 0!==n&&(a=n)}}return a}c=c||0;for(var i=e.length;i>0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[f,b,c]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,b){if(1&b&&(e=this(e)),8&b)return e;if("object"==typeof e&&e){if(4&b&&e.__esModule)return e;if(16&b&&"function"==typeof e.then)return e}var c=Object.create(null);r.r(c);var d={};a=a||[null,f({}),f([]),f(f)];for(var t=2&b&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>d[a]=()=>e[a]));return d.default=()=>e,r.d(c,d),c},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({40:"8eef7690",53:"935f2afb",154:"11d58a17",216:"2f4673e5",391:"20cdecc4",548:"bf5c5542",568:"c66bbf8a",643:"e7fdf6d9",783:"7c6883b5",836:"0480b142",846:"a683e47f",895:"dc9281b9",907:"c4f50fcb",1031:"5603335d",1190:"8cd4fd18",1351:"974203ee",1619:"db59132a",1760:"ec0d5d9e",1763:"2c8b636f",1857:"ed8448fe",1865:"0d9a188d",2005:"b0fc3de5",2023:"e1b2cf59",2156:"c108e81c",2229:"b7cd4035",2238:"9d55bf96",2242:"5c838b7d",2288:"93bf47d2",2356:"a708fa78",2389:"3a1ed2bb",2510:"1dba1ecf",2534:"b70ea2cb",2547:"4eac74de",2579:"bacc1ae0",3022:"59e5a646",3052:"7d6336d8",3217:"3b8c55ea",3242:"3fcb412e",3514:"12682444",3523:"bbedbacb",3695:"85c70040",3902:"30fb9660",3939:"07e6d80c",3996:"1c30975d",4111:"efdb11b6",4128:"a09c2993",4178:"1b064146",4248:"4fb2362d",4292:"8f41530a",4345:"8c9fcf50",4404:"7196cdd1",4428:"fc618254",4497:"fcff9033",4642:"422308df",4781:"0fb10398",4815:"bc8dcae3",4993:"c698fe77",5082:"c73303db",5178:"7b11c903",5221:"fd1ae250",5243:"c9ca4745",5245:"dbbf7db4",5255:"6ec64a11",5384:"6739d7ff",5523:"5af9b662",5581:"3847b3ea",5593:"99ed3086",5754:"a932041a",5781:"24e97898",5841:"0a1e161c",5873:"29ca1a0e",5927:"5281b7a2",5954:"6af0c1ea",5964:"22539a87",6013:"096837f0",6039:"f2ef54d0",6148:"fa2b770f",6236:"e3d8f98f",6252:"62c6dc45",6300:"ae417a11",6325:"c12dc9fd",6352:"dea0f9ea",6534:"bc344202",6578:"faa9d310",6705:"7d415946",6842:"9dbb4f95",7028:"c853dc39",7029:"101be56a",7080:"4d54d076",7092:"bffae3e7",7114:"b9421f89",7220:"695a8bbb",7239:"72e14192",7262:"9e350ec0",7395:"4fa03c51",7497:"621c6848",7499:"6b8e46b3",7551:"4351fb58",7591:"a8f67d08",7677:"d40dbec5",7868:"0390b328",7918:"17896441",7920:"1a4e3797",8050:"9748995c",8084:"5bc37772",8180:"3e4c86d4",8301:"72ffabc7",8411:"bdb5eb86",8841:"44b2adf6",8976:"b7730d0d",9212:"48ae5635",9214:"d7561401",9269:"34f2f592",9291:"70b084fe",9514:"1be78505",9722:"e36340b6",9829:"9ff53b5b"}[e]||e)+"."+{40:"687f1101",53:"da0a9203",154:"d706823d",216:"680a6df6",391:"5375813a",548:"4f1330ce",568:"1acc839f",643:"de866fbb",783:"468dab34",836:"32575a54",846:"b8f20d95",895:"8b8ee3c8",907:"b3a1918d",1031:"05cbde15",1190:"5dd67d55",1351:"4618b9f3",1619:"6f50c1d0",1760:"2c250436",1763:"b2f1412e",1857:"b3589d7f",1865:"1186d693",2005:"3454cfc2",2023:"b8a8ffb4",2156:"619f3030",2229:"0ab6a66d",2238:"47c09e6a",2242:"8c56c538",2288:"cca23454",2356:"2bb257f2",2389:"12630a9f",2510:"4673d8c6",2534:"99ee2f04",2547:"fb8596ee",2579:"816015a9",3022:"e9edd18a",3052:"d9e3c66f",3217:"d50f0d5a",3242:"d61d4ab6",3514:"4416d267",3523:"9fcac33b",3695:"e0419889",3902:"e3f700a3",3939:"53b2fbd7",3996:"c04b6b62",4111:"c5386572",4128:"479588b5",4178:"b78fd6fa",4248:"43d62e16",4292:"3235cd00",4345:"e1bd2694",4404:"5bf303c3",4428:"c686b75c",4497:"b18535a7",4642:"c748cc2d",4781:"a6ee55bc",4815:"4c7ec3a0",4972:"e3352a90",4993:"164c142f",5082:"be916204",5178:"ce482ce3",5221:"0fe36588",5243:"da4f0967",5245:"c7332918",5255:"ac3c351f",5384:"89c2e76b",5523:"988a70e9",5581:"5b5ccf89",5593:"694e142d",5754:"d5e014b0",5781:"70b78e51",5841:"488453fa",5873:"4d91cc87",5927:"ceaf1ffc",5954:"4be63f6e",5964:"ca79dac7",6013:"771b8b12",6039:"4af2136b",6148:"4d309065",6236:"c2802ab1",6252:"d4fbe534",6300:"d3ca84d8",6325:"1b6a252d",6352:"313a6052",6534:"a00f1fb9",6578:"9de6aa31",6705:"1d8d923e",6780:"2f5c1e5a",6842:"ea996f10",6945:"8e8e2060",7028:"2fc0de50",7029:"8ca0113a",7080:"6a163bd0",7092:"d34bc0df",7114:"bce75c8a",7220:"23b6fade",7239:"5d76082f",7262:"513719f1",7395:"ad054cf8",7497:"a891e5b6",7499:"2a4f2d74",7551:"2ba23a80",7591:"d837a742",7677:"3ea65837",7868:"2bf1bb4b",7918:"5c745bdc",7920:"be02ef92",8050:"8c0b6d5e",8084:"1188e660",8180:"eaafa28e",8301:"d08704ae",8411:"b95ff3d4",8841:"28ae2c3b",8894:"46125374",8976:"1c52ffde",9212:"4f79be50",9214:"2cac3291",9269:"86fae0eb",9291:"021d30e0",9514:"f8b40e6f",9722:"8972753a",9829:"5c60e5b7"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),b={},c="website:",r.l=(e,a,f,d)=>{if(b[e])b[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i<n.length;i++){var u=n[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==c+f){t=u;break}}t||(o=!0,(t=document.createElement("script")).charset="utf-8",t.timeout=120,r.nc&&t.setAttribute("nonce",r.nc),t.setAttribute("data-webpack",c+f),t.src=e),b[e]=[a];var l=(a,f)=>{t.onerror=t.onload=null,clearTimeout(s);var c=b[e];if(delete b[e],t.parentNode&&t.parentNode.removeChild(t),c&&c.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/eraser/docs/",r.gca=function(e){return e={12682444:"3514",17896441:"7918","8eef7690":"40","935f2afb":"53","11d58a17":"154","2f4673e5":"216","20cdecc4":"391",bf5c5542:"548",c66bbf8a:"568",e7fdf6d9:"643","7c6883b5":"783","0480b142":"836",a683e47f:"846",dc9281b9:"895",c4f50fcb:"907","5603335d":"1031","8cd4fd18":"1190","974203ee":"1351",db59132a:"1619",ec0d5d9e:"1760","2c8b636f":"1763",ed8448fe:"1857","0d9a188d":"1865",b0fc3de5:"2005",e1b2cf59:"2023",c108e81c:"2156",b7cd4035:"2229","9d55bf96":"2238","5c838b7d":"2242","93bf47d2":"2288",a708fa78:"2356","3a1ed2bb":"2389","1dba1ecf":"2510",b70ea2cb:"2534","4eac74de":"2547",bacc1ae0:"2579","59e5a646":"3022","7d6336d8":"3052","3b8c55ea":"3217","3fcb412e":"3242",bbedbacb:"3523","85c70040":"3695","30fb9660":"3902","07e6d80c":"3939","1c30975d":"3996",efdb11b6:"4111",a09c2993:"4128","1b064146":"4178","4fb2362d":"4248","8f41530a":"4292","8c9fcf50":"4345","7196cdd1":"4404",fc618254:"4428",fcff9033:"4497","422308df":"4642","0fb10398":"4781",bc8dcae3:"4815",c698fe77:"4993",c73303db:"5082","7b11c903":"5178",fd1ae250:"5221",c9ca4745:"5243",dbbf7db4:"5245","6ec64a11":"5255","6739d7ff":"5384","5af9b662":"5523","3847b3ea":"5581","99ed3086":"5593",a932041a:"5754","24e97898":"5781","0a1e161c":"5841","29ca1a0e":"5873","5281b7a2":"5927","6af0c1ea":"5954","22539a87":"5964","096837f0":"6013",f2ef54d0:"6039",fa2b770f:"6148",e3d8f98f:"6236","62c6dc45":"6252",ae417a11:"6300",c12dc9fd:"6325",dea0f9ea:"6352",bc344202:"6534",faa9d310:"6578","7d415946":"6705","9dbb4f95":"6842",c853dc39:"7028","101be56a":"7029","4d54d076":"7080",bffae3e7:"7092",b9421f89:"7114","695a8bbb":"7220","72e14192":"7239","9e350ec0":"7262","4fa03c51":"7395","621c6848":"7497","6b8e46b3":"7499","4351fb58":"7551",a8f67d08:"7591",d40dbec5:"7677","0390b328":"7868","1a4e3797":"7920","9748995c":"8050","5bc37772":"8084","3e4c86d4":"8180","72ffabc7":"8301",bdb5eb86:"8411","44b2adf6":"8841",b7730d0d:"8976","48ae5635":"9212",d7561401:"9214","34f2f592":"9269","70b084fe":"9291","1be78505":"9514",e36340b6:"9722","9ff53b5b":"9829"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,f)=>{var b=r.o(e,a)?e[a]:void 0;if(0!==b)if(b)f.push(b[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var c=new Promise(((f,c)=>b=e[a]=[f,c]));f.push(b[2]=c);var d=r.p+r.u(a),t=new Error;r.l(d,(f=>{if(r.o(e,a)&&(0!==(b=e[a])&&(e[a]=void 0),b)){var c=f&&("load"===f.type?"missing":f.type),d=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+c+": "+d+")",t.name="ChunkLoadError",t.type=c,t.request=d,b[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var b,c,d=f[0],t=f[1],o=f[2],n=0;if(d.some((a=>0!==e[a]))){for(b in t)r.o(t,b)&&(r.m[b]=t[b]);if(o)var i=o(r)}for(a&&a(f);n<d.length;n++)c=d[n],r.o(e,c)&&e[c]&&e[c][0](),e[c]=0;return r.O(i)},f=self.webpackChunkwebsite=self.webpackChunkwebsite||[];f.forEach(a.bind(null,0)),f.push=a.bind(null,f.push.bind(f))})()})(); \ No newline at end of file diff --git a/docs/assets/js/runtime~main.7ab14693.js b/docs/assets/js/runtime~main.7ab14693.js new file mode 100644 index 0000000000..e265fb1fe5 --- /dev/null +++ b/docs/assets/js/runtime~main.7ab14693.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,a,f,b,d,c={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={id:e,loaded:!1,exports:{}};return c[e].call(f.exports,f,f.exports,r),f.loaded=!0,f.exports}r.m=c,r.c=t,e=[],r.O=(a,f,b,d)=>{if(!f){var c=1/0;for(i=0;i<e.length;i++){f=e[i][0],b=e[i][1],d=e[i][2];for(var t=!0,o=0;o<f.length;o++)(!1&d||c>=d)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,d<c&&(c=d));if(t){e.splice(i--,1);var n=b();void 0!==n&&(a=n)}}return a}d=d||0;for(var i=e.length;i>0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[f,b,d]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,b){if(1&b&&(e=this(e)),8&b)return e;if("object"==typeof e&&e){if(4&b&&e.__esModule)return e;if(16&b&&"function"==typeof e.then)return e}var d=Object.create(null);r.r(d);var c={};a=a||[null,f({}),f([]),f(f)];for(var t=2&b&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>c[a]=()=>e[a]));return c.default=()=>e,r.d(d,c),d},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({40:"8eef7690",53:"935f2afb",154:"11d58a17",216:"2f4673e5",391:"20cdecc4",548:"bf5c5542",568:"c66bbf8a",643:"e7fdf6d9",783:"7c6883b5",836:"0480b142",846:"a683e47f",895:"dc9281b9",907:"c4f50fcb",1031:"5603335d",1190:"8cd4fd18",1351:"974203ee",1619:"db59132a",1760:"ec0d5d9e",1763:"2c8b636f",1857:"ed8448fe",1865:"0d9a188d",2005:"b0fc3de5",2023:"e1b2cf59",2156:"c108e81c",2229:"b7cd4035",2238:"9d55bf96",2242:"5c838b7d",2288:"93bf47d2",2356:"a708fa78",2389:"3a1ed2bb",2510:"1dba1ecf",2534:"b70ea2cb",2547:"4eac74de",2579:"bacc1ae0",3022:"59e5a646",3052:"7d6336d8",3217:"3b8c55ea",3242:"3fcb412e",3514:"12682444",3523:"bbedbacb",3695:"85c70040",3902:"30fb9660",3939:"07e6d80c",3996:"1c30975d",4111:"efdb11b6",4128:"a09c2993",4178:"1b064146",4248:"4fb2362d",4292:"8f41530a",4345:"8c9fcf50",4368:"a94703ab",4404:"7196cdd1",4428:"fc618254",4497:"fcff9033",4642:"422308df",4781:"0fb10398",4815:"bc8dcae3",4993:"c698fe77",5082:"c73303db",5178:"7b11c903",5221:"fd1ae250",5243:"c9ca4745",5245:"dbbf7db4",5255:"6ec64a11",5384:"6739d7ff",5523:"5af9b662",5581:"3847b3ea",5593:"99ed3086",5754:"a932041a",5781:"24e97898",5841:"0a1e161c",5873:"29ca1a0e",5927:"5281b7a2",5954:"6af0c1ea",5964:"22539a87",6013:"096837f0",6039:"f2ef54d0",6148:"fa2b770f",6236:"e3d8f98f",6252:"62c6dc45",6300:"ae417a11",6325:"c12dc9fd",6352:"dea0f9ea",6534:"bc344202",6578:"faa9d310",6705:"7d415946",6842:"9dbb4f95",7028:"c853dc39",7029:"101be56a",7080:"4d54d076",7092:"bffae3e7",7114:"b9421f89",7220:"695a8bbb",7239:"72e14192",7262:"9e350ec0",7395:"4fa03c51",7497:"621c6848",7499:"6b8e46b3",7551:"4351fb58",7591:"a8f67d08",7677:"d40dbec5",7868:"0390b328",7918:"17896441",7920:"1a4e3797",8050:"9748995c",8084:"5bc37772",8180:"3e4c86d4",8301:"72ffabc7",8411:"bdb5eb86",8518:"a7bd4aaa",8841:"44b2adf6",8976:"b7730d0d",9212:"48ae5635",9214:"d7561401",9269:"34f2f592",9291:"70b084fe",9661:"5e95c892",9722:"e36340b6",9829:"9ff53b5b"}[e]||e)+"."+{40:"ca5fd282",53:"0a68307c",154:"c673924e",216:"187f339b",391:"7ca62856",548:"ec01ec49",568:"13446857",643:"94d9b31c",783:"a26ba92b",836:"652e6bd1",846:"6b48266e",895:"7ca1886c",907:"ddfb9faa",1031:"b23ecd98",1190:"5d94802b",1351:"db23a97e",1426:"be67a35e",1619:"bdd9cb70",1760:"3d394cb4",1763:"733d78b2",1772:"61f6592f",1857:"485bf575",1865:"65d8092e",2005:"be5ce799",2023:"5eb99ea6",2156:"3dfa39c8",2229:"d3c04a53",2238:"48d408b8",2242:"abeb9ef9",2288:"597826fd",2356:"54aaa7fc",2389:"18ad5ad5",2510:"d433b521",2534:"1f9cdb37",2547:"cd66025d",2579:"c11996b0",3022:"d59d85e0",3052:"545b329a",3217:"4ab0bf60",3242:"54c127a8",3514:"bf167c14",3523:"734bd7d6",3695:"6420b355",3902:"273b686e",3939:"5396be34",3996:"740a287b",4111:"0bcb2915",4128:"9909da7a",4178:"869a4cad",4248:"5120e8b9",4292:"d1d7746f",4345:"cf3bd3d7",4368:"5018fc8a",4404:"e3825316",4428:"e65d5a68",4497:"00614336",4642:"b9cbb4dc",4781:"6b984536",4815:"deeb5da5",4993:"a9373167",5082:"0eee1cb1",5178:"40de134e",5221:"8a9454eb",5243:"e2a7d363",5245:"ad052b4c",5255:"e804f073",5384:"c14998ff",5523:"48bb081f",5581:"43247e52",5593:"1ed71bcf",5754:"2d3e796f",5781:"33651e6b",5841:"488453fa",5873:"1424cf4d",5927:"981f96dc",5954:"e59808b7",5964:"31d0f153",6013:"c3c4e65e",6039:"06e099a0",6148:"f4f734aa",6236:"a2c52a4d",6252:"beacabe7",6300:"3d424f98",6325:"ade4b346",6352:"7a05a9de",6534:"0b3ac2c6",6578:"5838e10c",6705:"b8046362",6842:"67a9bc2d",6945:"8e8e2060",7028:"861078cc",7029:"d26e4b44",7080:"d5641f32",7092:"d211ec7b",7114:"292245b3",7220:"ab71b31c",7239:"52383938",7262:"5d832f0e",7395:"7f9609b5",7497:"a891e5b6",7499:"1f13278c",7551:"d28caec9",7591:"9df77a9f",7677:"8e7bd9d0",7868:"50c3d7e8",7918:"6d94e406",7920:"cdef43d5",8050:"9c31807a",8084:"c2ae9680",8180:"0b3602b2",8301:"89379632",8411:"9d21e19a",8518:"45274bc2",8841:"95473760",8894:"46125374",8976:"88998729",9212:"ae8b4c4e",9214:"72651373",9269:"2d883d56",9291:"e3b3cc0e",9661:"b00730d7",9722:"4feb6f73",9829:"7090781c"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),b={},d="website:",r.l=(e,a,f,c)=>{if(b[e])b[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i<n.length;i++){var u=n[i];if(u.getAttribute("src")==e||u.getAttribute("data-webpack")==d+f){t=u;break}}t||(o=!0,(t=document.createElement("script")).charset="utf-8",t.timeout=120,r.nc&&t.setAttribute("nonce",r.nc),t.setAttribute("data-webpack",d+f),t.src=e),b[e]=[a];var l=(a,f)=>{t.onerror=t.onload=null,clearTimeout(s);var d=b[e];if(delete b[e],t.parentNode&&t.parentNode.removeChild(t),d&&d.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=l.bind(null,t.onerror),t.onload=l.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/eraser/docs/",r.gca=function(e){return e={12682444:"3514",17896441:"7918","8eef7690":"40","935f2afb":"53","11d58a17":"154","2f4673e5":"216","20cdecc4":"391",bf5c5542:"548",c66bbf8a:"568",e7fdf6d9:"643","7c6883b5":"783","0480b142":"836",a683e47f:"846",dc9281b9:"895",c4f50fcb:"907","5603335d":"1031","8cd4fd18":"1190","974203ee":"1351",db59132a:"1619",ec0d5d9e:"1760","2c8b636f":"1763",ed8448fe:"1857","0d9a188d":"1865",b0fc3de5:"2005",e1b2cf59:"2023",c108e81c:"2156",b7cd4035:"2229","9d55bf96":"2238","5c838b7d":"2242","93bf47d2":"2288",a708fa78:"2356","3a1ed2bb":"2389","1dba1ecf":"2510",b70ea2cb:"2534","4eac74de":"2547",bacc1ae0:"2579","59e5a646":"3022","7d6336d8":"3052","3b8c55ea":"3217","3fcb412e":"3242",bbedbacb:"3523","85c70040":"3695","30fb9660":"3902","07e6d80c":"3939","1c30975d":"3996",efdb11b6:"4111",a09c2993:"4128","1b064146":"4178","4fb2362d":"4248","8f41530a":"4292","8c9fcf50":"4345",a94703ab:"4368","7196cdd1":"4404",fc618254:"4428",fcff9033:"4497","422308df":"4642","0fb10398":"4781",bc8dcae3:"4815",c698fe77:"4993",c73303db:"5082","7b11c903":"5178",fd1ae250:"5221",c9ca4745:"5243",dbbf7db4:"5245","6ec64a11":"5255","6739d7ff":"5384","5af9b662":"5523","3847b3ea":"5581","99ed3086":"5593",a932041a:"5754","24e97898":"5781","0a1e161c":"5841","29ca1a0e":"5873","5281b7a2":"5927","6af0c1ea":"5954","22539a87":"5964","096837f0":"6013",f2ef54d0:"6039",fa2b770f:"6148",e3d8f98f:"6236","62c6dc45":"6252",ae417a11:"6300",c12dc9fd:"6325",dea0f9ea:"6352",bc344202:"6534",faa9d310:"6578","7d415946":"6705","9dbb4f95":"6842",c853dc39:"7028","101be56a":"7029","4d54d076":"7080",bffae3e7:"7092",b9421f89:"7114","695a8bbb":"7220","72e14192":"7239","9e350ec0":"7262","4fa03c51":"7395","621c6848":"7497","6b8e46b3":"7499","4351fb58":"7551",a8f67d08:"7591",d40dbec5:"7677","0390b328":"7868","1a4e3797":"7920","9748995c":"8050","5bc37772":"8084","3e4c86d4":"8180","72ffabc7":"8301",bdb5eb86:"8411",a7bd4aaa:"8518","44b2adf6":"8841",b7730d0d:"8976","48ae5635":"9212",d7561401:"9214","34f2f592":"9269","70b084fe":"9291","5e95c892":"9661",e36340b6:"9722","9ff53b5b":"9829"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,f)=>{var b=r.o(e,a)?e[a]:void 0;if(0!==b)if(b)f.push(b[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var d=new Promise(((f,d)=>b=e[a]=[f,d]));f.push(b[2]=d);var c=r.p+r.u(a),t=new Error;r.l(c,(f=>{if(r.o(e,a)&&(0!==(b=e[a])&&(e[a]=void 0),b)){var d=f&&("load"===f.type?"missing":f.type),c=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+d+": "+c+")",t.name="ChunkLoadError",t.type=d,t.request=c,b[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var b,d,c=f[0],t=f[1],o=f[2],n=0;if(c.some((a=>0!==e[a]))){for(b in t)r.o(t,b)&&(r.m[b]=t[b]);if(o)var i=o(r)}for(a&&a(f);n<c.length;n++)d=c[n],r.o(e,d)&&e[d]&&e[d][0](),e[d]=0;return r.O(i)},f=self.webpackChunkwebsite=self.webpackChunkwebsite||[];f.forEach(a.bind(null,0)),f.push=a.bind(null,f.push.bind(f))})()})(); \ No newline at end of file diff --git a/docs/code-of-conduct.html b/docs/code-of-conduct.html index 105b4fda58..e2fedc4ba9 100644 --- a/docs/code-of-conduct.html +++ b/docs/code-of-conduct.html @@ -1,22 +1,24 @@ <!doctype html> -<html lang="en" dir="ltr" class="docs-wrapper docs-doc-page docs-version-v1.3.x plugin-docs plugin-id-default docs-doc-id-code-of-conduct" data-has-hydrated="false"> +<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-v1.3.x docs-doc-page docs-doc-id-code-of-conduct" data-has-hydrated="false"> <head> <meta charset="UTF-8"> -<meta name="generator" content="Docusaurus v2.4.3"> -<title data-rh="true">Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/contributing.html b/docs/contributing.html index f501ba680e..bb142778e9 100644 --- a/docs/contributing.html +++ b/docs/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/custom-scanner.html b/docs/custom-scanner.html index fd670632b0..d4000e134a 100644 --- a/docs/custom-scanner.html +++ b/docs/custom-scanner.html @@ -1,22 +1,23 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: v1.3.x

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, use the following template.

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

When complete, provide your custom scanner image to Eraser in deployment.

- - +
Version: v1.3.x

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, use the following template.

+

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

+

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

+

When complete, provide your custom scanner image to Eraser in deployment.

\ No newline at end of file diff --git a/docs/customization.html b/docs/customization.html index 2ea877a2ff..24d34d714a 100644 --- a/docs/customization.html +++ b/docs/customization.html @@ -1,56 +1,95 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: v1.3.x

Customization

Overview

Eraser uses a configmap to configure its behavior. The configmap is part of the +

Version: v1.3.x

Customization

Overview

+

Eraser uses a configmap to configure its behavior. The configmap is part of the deployment and it is not necessary to deploy it manually. Once deployed, the configmap -can be edited at any time:

kubectl edit configmap --namespace eraser-system eraser-manager-config

If an eraser job is already running, the changes will not take effect until the job completes. -The configuration is in yaml.

Key Concepts

Basic architecture

The manager runs as a pod in your cluster and manages ImageJobs. Think of +can be edited at any time:

+
kubectl edit configmap --namespace eraser-system eraser-manager-config
+

If an eraser job is already running, the changes will not take effect until the job completes. +The configuration is in yaml.

+

Key Concepts

+

Basic architecture

+

The manager runs as a pod in your cluster and manages ImageJobs. Think of an ImageJob as a unit of work, performed on every node in your cluster. Each node runs a sub-job. The goal of the ImageJob is to assess the images on your -cluster's nodes, and to remove the images you don't want. There are two stages:

  1. Assessment
  2. Removal.

Scheduling

An ImageJob can either be created on-demand (see Manual Removal), +cluster's nodes, and to remove the images you don't want. There are two stages:

+
    +
  1. Assessment
  2. +
  3. Removal.
  4. +
+

Scheduling

+

An ImageJob can either be created on-demand (see Manual Removal), or they can be spawned on a timer like a cron job. On-demand jobs skip the assessment stage and get right down to the business of removing the images you specified. The behavior of an on-demand job is quite different from that of -timed jobs.

Fault Tolerance

Because an ImageJob runs on every node in your cluster, and the conditions on +timed jobs.

+

Fault Tolerance

+

Because an ImageJob runs on every node in your cluster, and the conditions on each node may vary widely, some of the sub-jobs may fail. If you cannot tolerate any failure, set the manager.imageJob.successRatio property to 1.0. If 75% success sounds good to you, set it to 0.75. In that case, if fewer than 75% of the pods spawned by the ImageJob report success, the job as -a whole will be marked as a failure.

This is mainly to help diagnose error conditions. As such, you can set +a whole will be marked as a failure.

+

This is mainly to help diagnose error conditions. As such, you can set manager.imageJob.cleanup.delayOnFailure to a long value so that logs can be -captured before the spawned pods are cleaned up.

Excluding Nodes

For various reasons, you may want to prevent Eraser from scheduling pods on +captured before the spawned pods are cleaned up.

+

Excluding Nodes

+

For various reasons, you may want to prevent Eraser from scheduling pods on certain nodes. To do so, the nodes can be given a special label. By default, this label is eraser.sh/cleanup.filter, but you can configure the behavior with -the options under manager.nodeFilter. The table provides more detail.

Configuring Components

An ImageJob is made up of various sub-jobs, with one sub-job for each node. -These sub-jobs can be broken down further into three stages.

  1. Collection (What is on the node?)
  2. Scanning (What images conform to the policy I've provided?)
  3. Removal (Remove images based on the results of the above)

Of the above stages, only Removal is mandatory. The others can be disabled. +the options under manager.nodeFilter. The table provides more detail.

+

Configuring Components

+

An ImageJob is made up of various sub-jobs, with one sub-job for each node. +These sub-jobs can be broken down further into three stages.

+
    +
  1. Collection (What is on the node?)
  2. +
  3. Scanning (What images conform to the policy I've provided?)
  4. +
  5. Removal (Remove images based on the results of the above)
  6. +
+

Of the above stages, only Removal is mandatory. The others can be disabled. Furthermore, manually triggered ImageJobs will skip right to removal, even if Eraser is configured to collect and scan. Collection and Scanning will only -take place when:

  1. The collector and/or scanner components are enabled, AND
  2. The job was not triggered manually by creating an ImageList.

Swapping out components

The collector, scanner, and remover components can all be swapped out. This +take place when:

+
    +
  1. The collector and/or scanner components are enabled, AND
  2. +
  3. The job was not triggered manually by creating an ImageList.
  4. +
+

Swapping out components

+

The collector, scanner, and remover components can all be swapped out. This enables you to build and host the images yourself. In addition, the scanner's behavior can be completely tailored to your needs by swapping out the default image with one of your own. To specify the images, use the components.<component>.image.repo and components.<component>.image.tag, -where <component> is one of collector, scanner, or remover.

Universal Options

The following portions of the configmap apply no matter how you spawn your +where <component> is one of collector, scanner, or remover.

+

Universal Options

+

The following portions of the configmap apply no matter how you spawn your ImageJob. The values provided below are the defaults. For more detail on -these options, see the table.

manager:
runtime:
name: containerd
address: unix:///run/containerd/containerd.sock
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Component Options

components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Scanner Options

These options can be provided to components.scanner.config. They will be +these options, see the table.

+
manager:
runtime:
name: containerd
address: unix:///run/containerd/containerd.sock
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Component Options

+
components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Scanner Options

+

These options can be provided to components.scanner.config. They will be passed through as a string to the scanner container and parsed there. If you -want to configure your own scanner, you must provide some way to parse this.

Below are the values recognized by the provided eraser-trivy-scanner image. -Values provided below are the defaults.

cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more information
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted

Detailed Options

OptionDescriptionDefault
manager.runtime.nameThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.runtime.addressThe runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions.unix:///run/containerd/containerd.sock
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
- - +want to configure your own scanner, you must provide some way to parse this.

+

Below are the values recognized by the provided eraser-trivy-scanner image. +Values provided below are the defaults.

+
cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more information
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted
+

Detailed Options

+
OptionDescriptionDefault
manager.runtime.nameThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.runtime.addressThe runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions.unix:///run/containerd/containerd.sock
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
\ No newline at end of file diff --git a/docs/exclusion.html b/docs/exclusion.html index e8d64d2a35..e59fec7ab7 100644 --- a/docs/exclusion.html +++ b/docs/exclusion.html @@ -1,22 +1,24 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: v1.3.x

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

- - +
Version: v1.3.x

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

\ No newline at end of file diff --git a/docs/faq.html b/docs/faq.html index c5a26185cc..e3fabb1699 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -1,22 +1,27 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: v1.3.x

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

How is Eraser different from Kubernetes garbage collection?

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

There are a couple core benefits to using Eraser for image cleanup:

  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
- - +
Version: v1.3.x

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

+

How is Eraser different from Kubernetes garbage collection?

+

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

+

There are a couple core benefits to using Eraser for image cleanup:

+
    +
  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • +
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
  • +
\ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 708e15550b..eded738182 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: v1.3.x

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: v1.3.x

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/installation.html b/docs/installation.html index 5c85842dcd..ecf4f2066b 100644 --- a/docs/installation.html +++ b/docs/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: v1.3.x

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: v1.3.x

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/manual-removal.html b/docs/manual-removal.html index d2ce953fc8..7d4b19d9b9 100644 --- a/docs/manual-removal.html +++ b/docs/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: v1.3.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: v1.3.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/metrics.html b/docs/metrics.html index a7f98627e6..61c97b689d 100644 --- a/docs/metrics.html +++ b/docs/metrics.html @@ -1,22 +1,26 @@ - + - -Metrics | Eraser Docs + +Metrics | Eraser Docs - - - + + + -
-
Version: v1.3.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

Below is the list of metrics provided by Eraser per run:

Eraser

- count
- name: images_removed_run_total
- description: Total images removed by eraser

Scanner

- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected

ImageJob

- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
- - +
Version: v1.3.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

+

Below is the list of metrics provided by Eraser per run:

+

Eraser

+
- count
- name: images_removed_run_total
- description: Total images removed by eraser
+

Scanner

+
- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected
+

ImageJob

+
- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
\ No newline at end of file diff --git a/docs/next.html b/docs/next.html index 45cdbc9b3e..1bb2ad2a4f 100644 --- a/docs/next.html +++ b/docs/next.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: Next

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: Next

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/next/architecture.html b/docs/next/architecture.html index ec3c418328..5111e5c0fd 100644 --- a/docs/next/architecture.html +++ b/docs/next/architecture.html @@ -1,27 +1,30 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Version: Next

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: Next

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/next/code-of-conduct.html b/docs/next/code-of-conduct.html index 56fdd400a8..6fa55975c8 100644 --- a/docs/next/code-of-conduct.html +++ b/docs/next/code-of-conduct.html @@ -1,22 +1,24 @@ - + - -Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/next/contributing.html b/docs/next/contributing.html index fe086af9a5..853fec3b4d 100644 --- a/docs/next/contributing.html +++ b/docs/next/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/next/custom-scanner.html b/docs/next/custom-scanner.html index 114fc79d9b..339e808811 100644 --- a/docs/next/custom-scanner.html +++ b/docs/next/custom-scanner.html @@ -1,22 +1,23 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: Next

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, use the following template.

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

When complete, provide your custom scanner image to Eraser in deployment.

- - +
Version: Next

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, use the following template.

+

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

+

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

+

When complete, provide your custom scanner image to Eraser in deployment.

\ No newline at end of file diff --git a/docs/next/customization.html b/docs/next/customization.html index cc37eb02fb..e4da8006bd 100644 --- a/docs/next/customization.html +++ b/docs/next/customization.html @@ -1,56 +1,95 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: Next

Customization

Overview

Eraser uses a configmap to configure its behavior. The configmap is part of the +

Version: Next

Customization

Overview

+

Eraser uses a configmap to configure its behavior. The configmap is part of the deployment and it is not necessary to deploy it manually. Once deployed, the configmap -can be edited at any time:

kubectl edit configmap --namespace eraser-system eraser-manager-config

If an eraser job is already running, the changes will not take effect until the job completes. -The configuration is in yaml.

Key Concepts

Basic architecture

The manager runs as a pod in your cluster and manages ImageJobs. Think of +can be edited at any time:

+
kubectl edit configmap --namespace eraser-system eraser-manager-config
+

If an eraser job is already running, the changes will not take effect until the job completes. +The configuration is in yaml.

+

Key Concepts

+

Basic architecture

+

The manager runs as a pod in your cluster and manages ImageJobs. Think of an ImageJob as a unit of work, performed on every node in your cluster. Each node runs a sub-job. The goal of the ImageJob is to assess the images on your -cluster's nodes, and to remove the images you don't want. There are two stages:

  1. Assessment
  2. Removal.

Scheduling

An ImageJob can either be created on-demand (see Manual Removal), +cluster's nodes, and to remove the images you don't want. There are two stages:

+
    +
  1. Assessment
  2. +
  3. Removal.
  4. +
+

Scheduling

+

An ImageJob can either be created on-demand (see Manual Removal), or they can be spawned on a timer like a cron job. On-demand jobs skip the assessment stage and get right down to the business of removing the images you specified. The behavior of an on-demand job is quite different from that of -timed jobs.

Fault Tolerance

Because an ImageJob runs on every node in your cluster, and the conditions on +timed jobs.

+

Fault Tolerance

+

Because an ImageJob runs on every node in your cluster, and the conditions on each node may vary widely, some of the sub-jobs may fail. If you cannot tolerate any failure, set the manager.imageJob.successRatio property to 1.0. If 75% success sounds good to you, set it to 0.75. In that case, if fewer than 75% of the pods spawned by the ImageJob report success, the job as -a whole will be marked as a failure.

This is mainly to help diagnose error conditions. As such, you can set +a whole will be marked as a failure.

+

This is mainly to help diagnose error conditions. As such, you can set manager.imageJob.cleanup.delayOnFailure to a long value so that logs can be -captured before the spawned pods are cleaned up.

Excluding Nodes

For various reasons, you may want to prevent Eraser from scheduling pods on +captured before the spawned pods are cleaned up.

+

Excluding Nodes

+

For various reasons, you may want to prevent Eraser from scheduling pods on certain nodes. To do so, the nodes can be given a special label. By default, this label is eraser.sh/cleanup.filter, but you can configure the behavior with -the options under manager.nodeFilter. The table provides more detail.

Configuring Components

An ImageJob is made up of various sub-jobs, with one sub-job for each node. -These sub-jobs can be broken down further into three stages.

  1. Collection (What is on the node?)
  2. Scanning (What images conform to the policy I've provided?)
  3. Removal (Remove images based on the results of the above)

Of the above stages, only Removal is mandatory. The others can be disabled. +the options under manager.nodeFilter. The table provides more detail.

+

Configuring Components

+

An ImageJob is made up of various sub-jobs, with one sub-job for each node. +These sub-jobs can be broken down further into three stages.

+
    +
  1. Collection (What is on the node?)
  2. +
  3. Scanning (What images conform to the policy I've provided?)
  4. +
  5. Removal (Remove images based on the results of the above)
  6. +
+

Of the above stages, only Removal is mandatory. The others can be disabled. Furthermore, manually triggered ImageJobs will skip right to removal, even if Eraser is configured to collect and scan. Collection and Scanning will only -take place when:

  1. The collector and/or scanner components are enabled, AND
  2. The job was not triggered manually by creating an ImageList.

Swapping out components

The collector, scanner, and remover components can all be swapped out. This +take place when:

+
    +
  1. The collector and/or scanner components are enabled, AND
  2. +
  3. The job was not triggered manually by creating an ImageList.
  4. +
+

Swapping out components

+

The collector, scanner, and remover components can all be swapped out. This enables you to build and host the images yourself. In addition, the scanner's behavior can be completely tailored to your needs by swapping out the default image with one of your own. To specify the images, use the components.<component>.image.repo and components.<component>.image.tag, -where <component> is one of collector, scanner, or remover.

Universal Options

The following portions of the configmap apply no matter how you spawn your +where <component> is one of collector, scanner, or remover.

+

Universal Options

+

The following portions of the configmap apply no matter how you spawn your ImageJob. The values provided below are the defaults. For more detail on -these options, see the table.

manager:
runtime:
name: containerd
address: unix:///run/containerd/containerd.sock
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Component Options

components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Scanner Options

These options can be provided to components.scanner.config. They will be +these options, see the table.

+
manager:
runtime:
name: containerd
address: unix:///run/containerd/containerd.sock
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Component Options

+
components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Scanner Options

+

These options can be provided to components.scanner.config. They will be passed through as a string to the scanner container and parsed there. If you -want to configure your own scanner, you must provide some way to parse this.

Below are the values recognized by the provided eraser-trivy-scanner image. -Values provided below are the defaults.

cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more information
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted

Detailed Options

OptionDescriptionDefault
manager.runtime.nameThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.runtime.addressThe runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions.unix:///run/containerd/containerd.sock
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
- - +want to configure your own scanner, you must provide some way to parse this.

+

Below are the values recognized by the provided eraser-trivy-scanner image. +Values provided below are the defaults.

+
cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more information
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
ignoredStatuses: # a list of trivy statuses to ignore. See https://aquasecurity.github.io/trivy/v0.44/docs/configuration/filtering/#by-status.
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted
+

Detailed Options

+
OptionDescriptionDefault
manager.runtime.nameThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.runtime.addressThe runtime socket address to use for the containers. Can provide a custom address for containerd and dockershim runtimes, but not for crio due to Trivy restrictions.unix:///run/containerd/containerd.sock
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
\ No newline at end of file diff --git a/docs/next/exclusion.html b/docs/next/exclusion.html index 0c171f6362..3cde257508 100644 --- a/docs/next/exclusion.html +++ b/docs/next/exclusion.html @@ -1,22 +1,24 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: Next

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

- - +
Version: Next

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

\ No newline at end of file diff --git a/docs/next/faq.html b/docs/next/faq.html index ac187de085..a90170b63f 100644 --- a/docs/next/faq.html +++ b/docs/next/faq.html @@ -1,22 +1,27 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: Next

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

How is Eraser different from Kubernetes garbage collection?

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

There are a couple core benefits to using Eraser for image cleanup:

  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
- - +
Version: Next

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

+

How is Eraser different from Kubernetes garbage collection?

+

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

+

There are a couple core benefits to using Eraser for image cleanup:

+
    +
  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • +
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
  • +
\ No newline at end of file diff --git a/docs/next/installation.html b/docs/next/installation.html index aa994afe35..c2988d22a0 100644 --- a/docs/next/installation.html +++ b/docs/next/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: Next

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: Next

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0-beta.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/next/manual-removal.html b/docs/next/manual-removal.html index 5d2bbaed81..6af00b8c7a 100644 --- a/docs/next/manual-removal.html +++ b/docs/next/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: Next

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: Next

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/next/metrics.html b/docs/next/metrics.html index 291f0bb40b..2f51af3522 100644 --- a/docs/next/metrics.html +++ b/docs/next/metrics.html @@ -1,22 +1,26 @@ - + - -Metrics | Eraser Docs + +Metrics | Eraser Docs - - - + + + -
-
Version: Next

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

Below is the list of metrics provided by Eraser per run:

Eraser

- count
- name: images_removed_run_total
- description: Total images removed by eraser

Scanner

- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected

ImageJob

- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
- - +
Version: Next

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

+

Below is the list of metrics provided by Eraser per run:

+

Eraser

+
- count
- name: images_removed_run_total
- description: Total images removed by eraser
+

Scanner

+
- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected
+

ImageJob

+
- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
\ No newline at end of file diff --git a/docs/next/quick-start.html b/docs/next/quick-start.html index 2258c15dce..11df5531df 100644 --- a/docs/next/quick-start.html +++ b/docs/next/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: Next

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: Next

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/next/release-management.html b/docs/next/release-management.html index 66fa101249..144c647799 100644 --- a/docs/next/release-management.html +++ b/docs/next/release-management.html @@ -1,22 +1,83 @@ - + - -Release Management | Eraser Docs + +Release Management | Eraser Docs - - - + + + -
-
Version: Next

Release Management

Overview

This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades.

Legend

  • X.Y.Z refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version.
  • Breaking changes refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility.
  • Milestone should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone.
  • Patch releases refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility.
  • Test gates should include soak tests and upgrade tests from the last minor version.

Release Versioning

All releases will be of the form vX.Y.Z where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning.

The rest of the doc will cover the release process for the following kinds of releases:

Major Releases

No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project

Minor Releases

  • X.Y.0-alpha.W, W >= 0 (Branch : main)
    • Released as needed before we cut a beta X.Y release
    • Alpha release, cut from master branch
  • X.Y.0-beta.W, W >= 0 (Branch : main)
    • Released as needed before we cut a stable X.Y release
    • More stable than the alpha release to signal users to test things out
    • Beta release, cut from master branch
  • X.Y.0-rc.W, W >= 0 (Branch : main)
    • Released as needed before we cut a stable X.Y release
    • soak for ~ 2 weeks before cutting a stable release
    • Release candidate release, cut from master branch
  • X.Y.0 (Branch: main)
    • Released every ~ 3 months
    • Stable release, cut from master when X.Y milestone is complete

Patch Releases

  • Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed)
    • No breaking changes
    • Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches.
    • Patch release, cut from a release-X.Y branch

Supported Releases

Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed.

We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible.

We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.

Supported Kubernetes Versions

Eraser is assumed to be compatible with the current Kubernetes Supported Versions per Kubernetes Supported Versions policy.

For example, if Eraser supported versions are v1.2 and v1.1, and Kubernetes supported versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time.

If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk.

Acknowledgement

This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm.

- - +
Version: Next

Release Management

+

Overview

+

This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades.

+

Legend

+
    +
  • X.Y.Z refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version.
  • +
  • Breaking changes refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility.
  • +
  • Milestone should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone.
  • +
  • Patch releases refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility.
  • +
  • Test gates should include soak tests and upgrade tests from the last minor version.
  • +
+

Release Versioning

+

All releases will be of the form vX.Y.Z where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning.

+

The rest of the doc will cover the release process for the following kinds of releases:

+

Major Releases

+

No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project

+

Minor Releases

+
    +
  • X.Y.0-alpha.W, W >= 0 (Branch : main) +
      +
    • Released as needed before we cut a beta X.Y release
    • +
    • Alpha release, cut from master branch
    • +
    +
  • +
  • X.Y.0-beta.W, W >= 0 (Branch : main) +
      +
    • Released as needed before we cut a stable X.Y release
    • +
    • More stable than the alpha release to signal users to test things out
    • +
    • Beta release, cut from master branch
    • +
    +
  • +
  • X.Y.0-rc.W, W >= 0 (Branch : main) +
      +
    • Released as needed before we cut a stable X.Y release
    • +
    • soak for ~ 2 weeks before cutting a stable release
    • +
    • Release candidate release, cut from master branch
    • +
    +
  • +
  • X.Y.0 (Branch: main) +
      +
    • Released every ~ 3 months
    • +
    • Stable release, cut from master when X.Y milestone is complete
    • +
    +
  • +
+

Patch Releases

+
    +
  • Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed) +
      +
    • No breaking changes
    • +
    • Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches.
    • +
    • Patch release, cut from a release-X.Y branch
    • +
    +
  • +
+

Supported Releases

+

Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed.

+

We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible.

+

We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.

+

Supported Kubernetes Versions

+

Eraser is assumed to be compatible with the current Kubernetes Supported Versions per Kubernetes Supported Versions policy.

+

For example, if Eraser supported versions are v1.2 and v1.1, and Kubernetes supported versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time.

+

If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk.

+

Acknowledgement

+

This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm.

\ No newline at end of file diff --git a/docs/next/releasing.html b/docs/next/releasing.html index 8de5384e4c..8805b568ee 100644 --- a/docs/next/releasing.html +++ b/docs/next/releasing.html @@ -1,23 +1,45 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: Next

Releasing

Create Release Pull Request

  1. Go to create_release_pull_request workflow under actions.
  2. Select run workflow, and use the workflow from your branch.
  3. Input release version with the semantic version identifying the release.
  4. Click run workflow and review the PR created by github-actions.

Releasing

  1. Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  2. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases

Notifying

  1. Send an email to the Eraser mailing list announcing the release, with links to GitHub.
  2. Post a message on the Eraser Slack channel with the same information.
- - +
Version: Next

Releasing

Create Release Pull Request

+
    +
  1. Go to create_release_pull_request workflow under actions.
  2. +
  3. Select run workflow, and use the workflow from your branch.
  4. +
  5. Input release version with the semantic version identifying the release.
  6. +
  7. Click run workflow and review the PR created by github-actions.
  8. +
+

Releasing

+
    +
  1. +

    Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  2. +
  3. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

    +
  4. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
+

Notifying

+
    +
  1. Send an email to the Eraser mailing list announcing the release, with links to GitHub.
  2. +
  3. Post a message on the Eraser Slack channel with the same information.
  4. +
\ No newline at end of file diff --git a/docs/next/setup.html b/docs/next/setup.html index 3a4f098374..12c6659965 100644 --- a/docs/next/setup.html +++ b/docs/next/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: Next

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-remover

Builds the docker image for eraser remover.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-remover

Builds the docker image for the eraser remover.

Configuration Options:

Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: Next

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-remover
  • +
+

Builds the docker image for eraser remover.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-remover
  • +
+

Builds the docker image for the eraser remover.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/next/trivy.html b/docs/next/trivy.html index af475984bb..6c0839783e 100644 --- a/docs/next/trivy.html +++ b/docs/next/trivy.html @@ -1,22 +1,20 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: Next

Trivy

Trivy Provider Options

The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

- - +
Version: Next

Trivy

Trivy Provider Options

+

The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

\ No newline at end of file diff --git a/docs/quick-start.html b/docs/quick-start.html index eb73ceaad2..61df684775 100644 --- a/docs/quick-start.html +++ b/docs/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: v1.3.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: v1.3.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/release-management.html b/docs/release-management.html index 7d07b7cfa2..ddfefd8f6e 100644 --- a/docs/release-management.html +++ b/docs/release-management.html @@ -1,22 +1,83 @@ - + - -Release Management | Eraser Docs + +Release Management | Eraser Docs - - - + + + -
-
Version: v1.3.x

Release Management

Overview

This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades.

Legend

  • X.Y.Z refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version.
  • Breaking changes refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility.
  • Milestone should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone.
  • Patch releases refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility.
  • Test gates should include soak tests and upgrade tests from the last minor version.

Release Versioning

All releases will be of the form vX.Y.Z where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning.

The rest of the doc will cover the release process for the following kinds of releases:

Major Releases

No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project

Minor Releases

  • X.Y.0-alpha.W, W >= 0 (Branch : main)
    • Released as needed before we cut a beta X.Y release
    • Alpha release, cut from master branch
  • X.Y.0-beta.W, W >= 0 (Branch : main)
    • Released as needed before we cut a stable X.Y release
    • More stable than the alpha release to signal users to test things out
    • Beta release, cut from master branch
  • X.Y.0-rc.W, W >= 0 (Branch : main)
    • Released as needed before we cut a stable X.Y release
    • soak for ~ 2 weeks before cutting a stable release
    • Release candidate release, cut from master branch
  • X.Y.0 (Branch: main)
    • Released every ~ 3 months
    • Stable release, cut from master when X.Y milestone is complete

Patch Releases

  • Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed)
    • No breaking changes
    • Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches.
    • Patch release, cut from a release-X.Y branch

Supported Releases

Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed.

We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible.

We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.

Supported Kubernetes Versions

Eraser is assumed to be compatible with the current Kubernetes Supported Versions per Kubernetes Supported Versions policy.

For example, if Eraser supported versions are v1.2 and v1.1, and Kubernetes supported versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time.

If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk.

Acknowledgement

This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm.

- - +
Version: v1.3.x

Release Management

+

Overview

+

This document describes Eraser project release management, which includes release versioning, supported releases, and supported upgrades.

+

Legend

+
    +
  • X.Y.Z refers to the version (git tag) of Eraser that is released. This is the version of the Eraser images and the Chart version.
  • +
  • Breaking changes refer to schema changes, flag changes, and behavior changes of Eraser that may require a clean installation during upgrade, and it may introduce changes that could break backward compatibility.
  • +
  • Milestone should be designed to include feature sets to accommodate 2 months release cycles including test gates. GitHub's milestones are used by maintainers to manage each release. PRs and Issues for each release should be created as part of a corresponding milestone.
  • +
  • Patch releases refer to applicable fixes, including security fixes, may be backported to support releases, depending on severity and feasibility.
  • +
  • Test gates should include soak tests and upgrade tests from the last minor version.
  • +
+

Release Versioning

+

All releases will be of the form vX.Y.Z where X is the major version, Y is the minor version and Z is the patch version. This project strictly follows semantic versioning.

+

The rest of the doc will cover the release process for the following kinds of releases:

+

Major Releases

+

No plan to move to 2.0.0 unless there is a major design change like an incompatible API change in the project

+

Minor Releases

+
    +
  • X.Y.0-alpha.W, W >= 0 (Branch : main) +
      +
    • Released as needed before we cut a beta X.Y release
    • +
    • Alpha release, cut from master branch
    • +
    +
  • +
  • X.Y.0-beta.W, W >= 0 (Branch : main) +
      +
    • Released as needed before we cut a stable X.Y release
    • +
    • More stable than the alpha release to signal users to test things out
    • +
    • Beta release, cut from master branch
    • +
    +
  • +
  • X.Y.0-rc.W, W >= 0 (Branch : main) +
      +
    • Released as needed before we cut a stable X.Y release
    • +
    • soak for ~ 2 weeks before cutting a stable release
    • +
    • Release candidate release, cut from master branch
    • +
    +
  • +
  • X.Y.0 (Branch: main) +
      +
    • Released every ~ 3 months
    • +
    • Stable release, cut from master when X.Y milestone is complete
    • +
    +
  • +
+

Patch Releases

+
    +
  • Patch Releases X.Y.Z, Z > 0 (Branch: release-X.Y, only cut when a patch is needed) +
      +
    • No breaking changes
    • +
    • Applicable fixes, including security fixes, may be cherry-picked from master into the latest supported minor release-X.Y branches.
    • +
    • Patch release, cut from a release-X.Y branch
    • +
    +
  • +
+

Supported Releases

+

Applicable fixes, including security fixes, may be cherry-picked into the release branch, depending on severity and feasibility. Patch releases are cut from that branch as needed.

+

We expect users to stay reasonably up-to-date with the versions of Eraser they use in production, but understand that it may take time to upgrade. We expect users to be running approximately the latest patch release of a given minor release and encourage users to upgrade as soon as possible.

+

We expect to "support" n (current) and n-1 major.minor releases. "Support" means we expect users to be running that version in production. For example, when v1.2.0 comes out, v1.0.x will no longer be supported for patches, and we encourage users to upgrade to a supported version as soon as possible.

+

Supported Kubernetes Versions

+

Eraser is assumed to be compatible with the current Kubernetes Supported Versions per Kubernetes Supported Versions policy.

+

For example, if Eraser supported versions are v1.2 and v1.1, and Kubernetes supported versions are v1.22, v1.23, v1.24, then all supported Eraser versions (v1.2, v1.1) are assumed to be compatible with all supported Kubernetes versions (v1.22, v1.23, v1.24). If Kubernetes v1.25 is released later, then Eraser v1.2 and v1.1 will be assumed to be compatible with v1.25 if those Eraser versions are still supported at that time.

+

If you choose to use Eraser with a version of Kubernetes that it does not support, you are using it at your own risk.

+

Acknowledgement

+

This document builds on the ideas and implementations of release processes from projects like Kubernetes and Helm.

\ No newline at end of file diff --git a/docs/releasing.html b/docs/releasing.html index 4549532ddb..97ffc5b865 100644 --- a/docs/releasing.html +++ b/docs/releasing.html @@ -1,23 +1,45 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: v1.3.x

Releasing

Create Release Pull Request

  1. Go to create_release_pull_request workflow under actions.
  2. Select run workflow, and use the workflow from your branch.
  3. Input release version with the semantic version identifying the release.
  4. Click run workflow and review the PR created by github-actions.

Releasing

  1. Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  2. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases

Notifying

  1. Send an email to the Eraser mailing list announcing the release, with links to GitHub.
  2. Post a message on the Eraser Slack channel with the same information.
- - +
Version: v1.3.x

Releasing

Create Release Pull Request

+
    +
  1. Go to create_release_pull_request workflow under actions.
  2. +
  3. Select run workflow, and use the workflow from your branch.
  4. +
  5. Input release version with the semantic version identifying the release.
  6. +
  7. Click run workflow and review the PR created by github-actions.
  8. +
+

Releasing

+
    +
  1. +

    Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  2. +
  3. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

    +
  4. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
+

Notifying

+
    +
  1. Send an email to the Eraser mailing list announcing the release, with links to GitHub.
  2. +
  3. Post a message on the Eraser Slack channel with the same information.
  4. +
\ No newline at end of file diff --git a/docs/search.html b/docs/search.html index 95a8f81ccd..7d6900919e 100644 --- a/docs/search.html +++ b/docs/search.html @@ -2,21 +2,18 @@ - -Search the documentation | Eraser Docs + +Search the documentation | Eraser Docs - - - + + + -
-

Search the documentation

- - +

Search the documentation

\ No newline at end of file diff --git a/docs/setup.html b/docs/setup.html index 10a27a2512..a2506b8757 100644 --- a/docs/setup.html +++ b/docs/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: v1.3.x

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-remover

Builds the docker image for eraser remover.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-remover

Builds the docker image for the eraser remover.

Configuration Options:

Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: v1.3.x

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-remover
  • +
+

Builds the docker image for eraser remover.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-remover
  • +
+

Builds the docker image for the eraser remover.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 9d2bff581a..e430414526 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -1 +1 @@ -https://eraser-dev.github.io/eraser/docs/searchweekly0.5https://eraser-dev.github.io/eraser/docs/nextweekly0.5https://eraser-dev.github.io/eraser/docs/next/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/next/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/next/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/next/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/next/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/next/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/next/faqweekly0.5https://eraser-dev.github.io/eraser/docs/next/installationweekly0.5https://eraser-dev.github.io/eraser/docs/next/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/next/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/next/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/next/release-managementweekly0.5https://eraser-dev.github.io/eraser/docs/next/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/next/setupweekly0.5https://eraser-dev.github.io/eraser/docs/next/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.xweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.xweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.xweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.xweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.xweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/weekly0.5https://eraser-dev.github.io/eraser/docs/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/faqweekly0.5https://eraser-dev.github.io/eraser/docs/installationweekly0.5https://eraser-dev.github.io/eraser/docs/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/release-managementweekly0.5https://eraser-dev.github.io/eraser/docs/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/setupweekly0.5https://eraser-dev.github.io/eraser/docs/trivyweekly0.5 \ No newline at end of file +https://eraser-dev.github.io/eraser/docs/searchweekly0.5https://eraser-dev.github.io/eraser/docs/nextweekly0.5https://eraser-dev.github.io/eraser/docs/next/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/next/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/next/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/next/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/next/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/next/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/next/faqweekly0.5https://eraser-dev.github.io/eraser/docs/next/installationweekly0.5https://eraser-dev.github.io/eraser/docs/next/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/next/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/next/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/next/release-managementweekly0.5https://eraser-dev.github.io/eraser/docs/next/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/next/setupweekly0.5https://eraser-dev.github.io/eraser/docs/next/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.xweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v0.4.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.xweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v0.5.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.xweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v1.0.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.xweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v1.1.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.xweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/faqweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/installationweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/setupweekly0.5https://eraser-dev.github.io/eraser/docs/v1.2.x/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/architectureweekly0.5https://eraser-dev.github.io/eraser/docs/code-of-conductweekly0.5https://eraser-dev.github.io/eraser/docs/contributingweekly0.5https://eraser-dev.github.io/eraser/docs/custom-scannerweekly0.5https://eraser-dev.github.io/eraser/docs/customizationweekly0.5https://eraser-dev.github.io/eraser/docs/exclusionweekly0.5https://eraser-dev.github.io/eraser/docs/faqweekly0.5https://eraser-dev.github.io/eraser/docs/installationweekly0.5https://eraser-dev.github.io/eraser/docs/manual-removalweekly0.5https://eraser-dev.github.io/eraser/docs/metricsweekly0.5https://eraser-dev.github.io/eraser/docs/quick-startweekly0.5https://eraser-dev.github.io/eraser/docs/release-managementweekly0.5https://eraser-dev.github.io/eraser/docs/releasingweekly0.5https://eraser-dev.github.io/eraser/docs/setupweekly0.5https://eraser-dev.github.io/eraser/docs/trivyweekly0.5https://eraser-dev.github.io/eraser/docs/weekly0.5 \ No newline at end of file diff --git a/docs/trivy.html b/docs/trivy.html index 1645dde70e..107a63acbc 100644 --- a/docs/trivy.html +++ b/docs/trivy.html @@ -1,22 +1,20 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: v1.3.x

Trivy

Trivy Provider Options

The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

- - +
Version: v1.3.x

Trivy

Trivy Provider Options

+

The Trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

\ No newline at end of file diff --git a/docs/v0.4.x.html b/docs/v0.4.x.html index a10f7dd408..874bad2274 100644 --- a/docs/v0.4.x.html +++ b/docs/v0.4.x.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: v0.4.x

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: v0.4.x

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/v0.4.x/architecture.html b/docs/v0.4.x/architecture.html index e66f621ed5..e3ac50c953 100644 --- a/docs/v0.4.x/architecture.html +++ b/docs/v0.4.x/architecture.html @@ -1,27 +1,31 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Version: v0.4.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: v0.4.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Note: metrics are not yet implemented in Eraser v0.4.x, but will be available in the upcoming v1.0.0 release.

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+

Note: metrics are not yet implemented in Eraser v0.4.x, but will be available in the upcoming v1.0.0 release.

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/v0.4.x/code-of-conduct.html b/docs/v0.4.x/code-of-conduct.html index 9bcb047bc2..e0307e515e 100644 --- a/docs/v0.4.x/code-of-conduct.html +++ b/docs/v0.4.x/code-of-conduct.html @@ -1,22 +1,24 @@ - + - -Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v0.4.x/contributing.html b/docs/v0.4.x/contributing.html index c3f1b5997c..15b4702284 100644 --- a/docs/v0.4.x/contributing.html +++ b/docs/v0.4.x/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v0.4.x/custom-scanner.html b/docs/v0.4.x/custom-scanner.html index 693819d6a6..3c385741ee 100644 --- a/docs/v0.4.x/custom-scanner.html +++ b/docs/v0.4.x/custom-scanner.html @@ -1,22 +1,21 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: v0.4.x

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, provide your scanner image to Eraser in deployment.

In order for the custom scanner to communicate with the collector and eraser containers, utilize ReadCollectScanPipe() to get the list of all non-running images to scan from collector. Then, use WriteScanErasePipe() to pass the images found non-compliant by your scanner to eraser for removal. Both functions can be found in util.

- - +
Version: v0.4.x

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, provide your scanner image to Eraser in deployment.

+

In order for the custom scanner to communicate with the collector and eraser containers, utilize ReadCollectScanPipe() to get the list of all non-running images to scan from collector. Then, use WriteScanErasePipe() to pass the images found non-compliant by your scanner to eraser for removal. Both functions can be found in util.

\ No newline at end of file diff --git a/docs/v0.4.x/customization.html b/docs/v0.4.x/customization.html index c04ac2ceea..c37833cb9c 100644 --- a/docs/v0.4.x/customization.html +++ b/docs/v0.4.x/customization.html @@ -1,22 +1,25 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: v0.4.x

Customization

By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:

  • --job-cleanup-on-success-delay: Duration to delay job deletion after successful runs. 0 means no delay. Defaults to 0.
  • --job-cleanup-on-error-delay: Duration to delay job deletion after errored runs. 0 means no delay. Defaults to 24h.
  • --job-success-ratio: Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to 1.0.

For duration, valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

- - +
Version: v0.4.x

Customization

By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:

+
    +
  • --job-cleanup-on-success-delay: Duration to delay job deletion after successful runs. 0 means no delay. Defaults to 0.
  • +
  • --job-cleanup-on-error-delay: Duration to delay job deletion after errored runs. 0 means no delay. Defaults to 24h.
  • +
  • --job-success-ratio: Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to 1.0.
  • +
+

For duration, valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

\ No newline at end of file diff --git a/docs/v0.4.x/exclusion.html b/docs/v0.4.x/exclusion.html index 052bc333a4..a29e849391 100644 --- a/docs/v0.4.x/exclusion.html +++ b/docs/v0.4.x/exclusion.html @@ -1,22 +1,32 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: v0.4.x

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<EOF
{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}
EOF

$ kubectl create configmap excluded --from-file=excluded=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes with --filter-nodes is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the --filter-nodes argument.

See Eraser Helm Chart for more information on deployment.

Nodes with the selector eraser.sh/cleanup.filter will be filtered accordingly.

  • If include is provided, eraser and collector pods will only be scheduled on nodes with the selector eraser.sh/cleanup.filter.
  • If exclude is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector eraser.sh/cleanup.filter.

Unless specified, the default value of --filter-nodes is exclude. Because Windows nodes are not supported, they will always be excluded regardless of the eraser.sh/cleanup.filter label or the value of --filter-nodes.

Additional node selectors can be provided through the --filter-nodes-selector flag.

- - +
Version: v0.4.x

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<EOF
{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}
EOF

$ kubectl create configmap excluded --from-file=excluded=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes with --filter-nodes is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the --filter-nodes argument.

+

See Eraser Helm Chart for more information on deployment.

+

Nodes with the selector eraser.sh/cleanup.filter will be filtered accordingly.

+
    +
  • If include is provided, eraser and collector pods will only be scheduled on nodes with the selector eraser.sh/cleanup.filter.
  • +
  • If exclude is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector eraser.sh/cleanup.filter.
  • +
+

Unless specified, the default value of --filter-nodes is exclude. Because Windows nodes are not supported, they will always be excluded regardless of the eraser.sh/cleanup.filter label or the value of --filter-nodes.

+

Additional node selectors can be provided through the --filter-nodes-selector flag.

\ No newline at end of file diff --git a/docs/v0.4.x/faq.html b/docs/v0.4.x/faq.html index d7bb900c4a..0b4db8f802 100644 --- a/docs/v0.4.x/faq.html +++ b/docs/v0.4.x/faq.html @@ -1,22 +1,20 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: v0.4.x

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the --severity flag.

- - +
Version: v0.4.x

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the --severity flag.

\ No newline at end of file diff --git a/docs/v0.4.x/installation.html b/docs/v0.4.x/installation.html index d658d6d2df..e6ffc2861c 100644 --- a/docs/v0.4.x/installation.html +++ b/docs/v0.4.x/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: v0.4.x

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.4.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: v0.4.x

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.4.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/v0.4.x/manual-removal.html b/docs/v0.4.x/manual-removal.html index 62eeee8e01..c0e20ae99c 100644 --- a/docs/v0.4.x/manual-removal.html +++ b/docs/v0.4.x/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: v0.4.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: v0.4.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/v0.4.x/quick-start.html b/docs/v0.4.x/quick-start.html index d9def93395..abbaa8f299 100644 --- a/docs/v0.4.x/quick-start.html +++ b/docs/v0.4.x/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: v0.4.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by --repeat-period argument to eraser-controller-manager. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by removing the --scanner-image argument. If you are deploying with Helm, use --set scanner.image.repository="" to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: v0.4.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by --repeat-period argument to eraser-controller-manager. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by removing the --scanner-image argument. If you are deploying with Helm, use --set scanner.image.repository="" to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/v0.4.x/releasing.html b/docs/v0.4.x/releasing.html index 56ccb069a5..8c0eda9784 100644 --- a/docs/v0.4.x/releasing.html +++ b/docs/v0.4.x/releasing.html @@ -1,23 +1,74 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: v0.4.x

Releasing

Overview

The release process consists of three phases: versioning, building, and publishing.

Versioning involves maintaining the following files:

  • Makefile - the Makefile contains a VERSION variable that defines the version of the project.
  • manager.yaml - the controller-manager deployment yaml contains the latest release tag image of the project.
  • eraser.yaml - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project.

The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release.

Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline.

Publishing involves creating a release tag and creating a new Release on GitHub.

Versioning

  1. Obtain a copy of the repository.

    git clone git@github.com:eraser-dev/eraser.git
  2. If this is a patch release for a release branch, check out applicable branch, such as release-0.1. If not, branch should be main

  3. Execute the release-patch target to generate patch. Give the semantic version of the release:

    make release-manifest NEWVERSION=vX.Y.Z
  4. Promote staging manifest to release.

    make promote-staging-manifest
  5. If it's a new minor release (e.g. v0.4.x -> 0.5.0), tag docs to be versioned. Make sure to keep patch version as .x for a minor release.

    make version-docs NEWVERSION=v0.5.x
  6. Preview the changes:

    git status
    git diff

Building and releasing

  1. Commit the changes and push to remote repository to create a pull request.

    git checkout -b release-<NEW VERSION>
    git commit -a -s -m "Prepare <NEW VERSION> release"
    git push <YOUR FORK>
  2. Once the PR is merged to main or release branch (<BRANCH NAME> below), tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  3. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/eraser and ghcr.io/eraser-dev/eraser-manager images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
- - +
Version: v0.4.x

Releasing

Overview

+

The release process consists of three phases: versioning, building, and publishing.

+

Versioning involves maintaining the following files:

+
    +
  • Makefile - the Makefile contains a VERSION variable that defines the version of the project.
  • +
  • manager.yaml - the controller-manager deployment yaml contains the latest release tag image of the project.
  • +
  • eraser.yaml - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project.
  • +
+

The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release.

+

Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline.

+

Publishing involves creating a release tag and creating a new Release on GitHub.

+

Versioning

+
    +
  1. +

    Obtain a copy of the repository.

    +
    git clone git@github.com:eraser-dev/eraser.git
    +
  2. +
  3. +

    If this is a patch release for a release branch, check out applicable branch, such as release-0.1. If not, branch should be main

    +
  4. +
  5. +

    Execute the release-patch target to generate patch. Give the semantic version of the release:

    +
    make release-manifest NEWVERSION=vX.Y.Z
    +
  6. +
  7. +

    Promote staging manifest to release.

    +
    make promote-staging-manifest
    +
  8. +
  9. +

    If it's a new minor release (e.g. v0.4.x -> 0.5.0), tag docs to be versioned. Make sure to keep patch version as .x for a minor release.

    +
    make version-docs NEWVERSION=v0.5.x
    +
  10. +
  11. +

    Preview the changes:

    +
    git status
    git diff
    +
  12. +
+

Building and releasing

+
    +
  1. +

    Commit the changes and push to remote repository to create a pull request.

    +
    git checkout -b release-<NEW VERSION>
    git commit -a -s -m "Prepare <NEW VERSION> release"
    git push <YOUR FORK>
    +
  2. +
  3. +

    Once the PR is merged to main or release branch (<BRANCH NAME> below), tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  4. +
  5. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/eraser and ghcr.io/eraser-dev/eraser-manager images automatically, then publish the new release tag.

    +
  6. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
\ No newline at end of file diff --git a/docs/v0.4.x/setup.html b/docs/v0.4.x/setup.html index 9f92580f96..4ae1487d9a 100644 --- a/docs/v0.4.x/setup.html +++ b/docs/v0.4.x/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: v0.4.x

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-eraser ERASER_IMG=eraser:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
eraser:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
ERASER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
ERASER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
ERASER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-eraser

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
ERASER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-eraser

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
ERASER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: v0.4.x

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-eraser ERASER_IMG=eraser:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
eraser:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
ERASER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-eraser
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
ERASER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-eraser
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/v0.4.x/trivy.html b/docs/v0.4.x/trivy.html index 6524be806c..7f268f5dd6 100644 --- a/docs/v0.4.x/trivy.html +++ b/docs/v0.4.x/trivy.html @@ -1,22 +1,26 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: v0.4.x

Trivy

Trivy Provider Options

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:

  • --ignore-unfixed: boolean to report only fixed vulnerabilities (default true)
  • --security-checks: comma-separated list of what security issues to detect (default "vuln")
  • --vuln-type: list of severity levels to report (default "CRITICAL")
  • --delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)
- - +
Version: v0.4.x

Trivy

Trivy Provider Options

+

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:

+
    +
  • --ignore-unfixed: boolean to report only fixed vulnerabilities (default true)
  • +
  • --security-checks: comma-separated list of what security issues to detect (default "vuln")
  • +
  • --vuln-type: list of severity levels to report (default "CRITICAL")
  • +
  • --delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)
  • +
\ No newline at end of file diff --git a/docs/v0.5.x.html b/docs/v0.5.x.html index 0740c6a2a2..ad4ed5bfb9 100644 --- a/docs/v0.5.x.html +++ b/docs/v0.5.x.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: v0.5.x

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: v0.5.x

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/v0.5.x/architecture.html b/docs/v0.5.x/architecture.html index 333ec8d759..13b1c3b6eb 100644 --- a/docs/v0.5.x/architecture.html +++ b/docs/v0.5.x/architecture.html @@ -1,27 +1,31 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Version: v0.5.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: v0.5.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Note: metrics are not yet implemented in Eraser v0.5.x, but will be available in the upcoming v1.0.0 release.

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+

Note: metrics are not yet implemented in Eraser v0.5.x, but will be available in the upcoming v1.0.0 release.

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/v0.5.x/code-of-conduct.html b/docs/v0.5.x/code-of-conduct.html index 50ad32fcdc..19e083c418 100644 --- a/docs/v0.5.x/code-of-conduct.html +++ b/docs/v0.5.x/code-of-conduct.html @@ -1,22 +1,24 @@ - + - -Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v0.5.x/contributing.html b/docs/v0.5.x/contributing.html index 83bbe3935b..f3d48842db 100644 --- a/docs/v0.5.x/contributing.html +++ b/docs/v0.5.x/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v0.5.x/custom-scanner.html b/docs/v0.5.x/custom-scanner.html index bdce9d5c14..3ee5fb1e81 100644 --- a/docs/v0.5.x/custom-scanner.html +++ b/docs/v0.5.x/custom-scanner.html @@ -1,22 +1,23 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: v0.5.x

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, use the following template.

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

When complete, provide your custom scanner image to Eraser in deployment.

- - +
Version: v0.5.x

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, use the following template.

+

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

+

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

+

When complete, provide your custom scanner image to Eraser in deployment.

\ No newline at end of file diff --git a/docs/v0.5.x/customization.html b/docs/v0.5.x/customization.html index 6dba257fce..9b967d092d 100644 --- a/docs/v0.5.x/customization.html +++ b/docs/v0.5.x/customization.html @@ -1,22 +1,25 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: v0.5.x

Customization

By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:

  • --job-cleanup-on-success-delay: Duration to delay job deletion after successful runs. 0 means no delay. Defaults to 0.
  • --job-cleanup-on-error-delay: Duration to delay job deletion after errored runs. 0 means no delay. Defaults to 24h.
  • --job-success-ratio: Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to 1.0.

For duration, valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

- - +
Version: v0.5.x

Customization

By default, successful jobs will be deleted after a period of time. You can change this behavior by setting the following flags in the eraser-controller-manager:

+
    +
  • --job-cleanup-on-success-delay: Duration to delay job deletion after successful runs. 0 means no delay. Defaults to 0.
  • +
  • --job-cleanup-on-error-delay: Duration to delay job deletion after errored runs. 0 means no delay. Defaults to 24h.
  • +
  • --job-success-ratio: Ratio of successful/total runs to consider a job successful. 1.0 means all runs must succeed. Defaults to 1.0.
  • +
+

For duration, valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

\ No newline at end of file diff --git a/docs/v0.5.x/exclusion.html b/docs/v0.5.x/exclusion.html index 6654dce339..c887c2c571 100644 --- a/docs/v0.5.x/exclusion.html +++ b/docs/v0.5.x/exclusion.html @@ -1,22 +1,32 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: v0.5.x

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<EOF
{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes with --filter-nodes is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the --filter-nodes argument.

See Eraser Helm Chart for more information on deployment.

Nodes with the selector eraser.sh/cleanup.filter will be filtered accordingly.

  • If include is provided, eraser and collector pods will only be scheduled on nodes with the selector eraser.sh/cleanup.filter.
  • If exclude is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector eraser.sh/cleanup.filter.

Unless specified, the default value of --filter-nodes is exclude. Because Windows nodes are not supported, they will always be excluded regardless of the eraser.sh/cleanup.filter label or the value of --filter-nodes.

Additional node selectors can be provided through the --filter-nodes-selector flag.

- - +
Version: v0.5.x

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<EOF
{"excluded": ["docker.io/library/*", "ghcr.io/eraser-dev/test:latest"]}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes with --filter-nodes is added in v0.3.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the --filter-nodes argument.

+

See Eraser Helm Chart for more information on deployment.

+

Nodes with the selector eraser.sh/cleanup.filter will be filtered accordingly.

+
    +
  • If include is provided, eraser and collector pods will only be scheduled on nodes with the selector eraser.sh/cleanup.filter.
  • +
  • If exclude is provided, eraser and collector pods will be scheduled on all nodes besides those with the selector eraser.sh/cleanup.filter.
  • +
+

Unless specified, the default value of --filter-nodes is exclude. Because Windows nodes are not supported, they will always be excluded regardless of the eraser.sh/cleanup.filter label or the value of --filter-nodes.

+

Additional node selectors can be provided through the --filter-nodes-selector flag.

\ No newline at end of file diff --git a/docs/v0.5.x/faq.html b/docs/v0.5.x/faq.html index ff10ce21a5..b5ad966898 100644 --- a/docs/v0.5.x/faq.html +++ b/docs/v0.5.x/faq.html @@ -1,22 +1,20 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: v0.5.x

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the --severity flag.

- - +
Version: v0.5.x

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured with the --severity flag.

\ No newline at end of file diff --git a/docs/v0.5.x/installation.html b/docs/v0.5.x/installation.html index 13ed83fa3b..ba7d9d8270 100644 --- a/docs/v0.5.x/installation.html +++ b/docs/v0.5.x/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: v0.5.x

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.5.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: v0.5.x

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v0.5.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/v0.5.x/manual-removal.html b/docs/v0.5.x/manual-removal.html index 531c1beedd..d1089c7077 100644 --- a/docs/v0.5.x/manual-removal.html +++ b/docs/v0.5.x/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: v0.5.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: v0.5.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/v0.5.x/quick-start.html b/docs/v0.5.x/quick-start.html index 9302343361..e3b4f4796f 100644 --- a/docs/v0.5.x/quick-start.html +++ b/docs/v0.5.x/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: v0.5.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by --repeat-period argument to eraser-controller-manager. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by removing the --scanner-image argument. If you are deploying with Helm, use --set scanner.image.repository="" to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: v0.5.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set by --repeat-period argument to eraser-controller-manager. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by removing the --scanner-image argument. If you are deploying with Helm, use --set scanner.image.repository="" to remove the scanner image. In this case, each collector pod will hold 2 containers: collector and eraser.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/v0.5.x/releasing.html b/docs/v0.5.x/releasing.html index 24901b654a..71f2223e79 100644 --- a/docs/v0.5.x/releasing.html +++ b/docs/v0.5.x/releasing.html @@ -1,23 +1,74 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: v0.5.x

Releasing

Overview

The release process consists of three phases: versioning, building, and publishing.

Versioning involves maintaining the following files:

  • Makefile - the Makefile contains a VERSION variable that defines the version of the project.
  • manager.yaml - the controller-manager deployment yaml contains the latest release tag image of the project.
  • eraser.yaml - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project.

The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release.

Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline.

Publishing involves creating a release tag and creating a new Release on GitHub.

Versioning

  1. Obtain a copy of the repository.

    git clone git@github.com:eraser-dev/eraser.git
  2. If this is a patch release for a release branch, check out applicable branch, such as release-0.1. If not, branch should be main

  3. Execute the release-patch target to generate patch. Give the semantic version of the release:

    make release-manifest NEWVERSION=vX.Y.Z
  4. Promote staging manifest to release.

    make promote-staging-manifest
  5. If it's a new minor release (e.g. v0.4.x -> 0.5.0), tag docs to be versioned. Make sure to keep patch version as .x for a minor release.

    make version-docs NEWVERSION=v0.5.x
  6. Preview the changes:

    git status
    git diff

Building and releasing

  1. Commit the changes and push to remote repository to create a pull request.

    git checkout -b release-<NEW VERSION>
    git commit -a -s -m "Prepare <NEW VERSION> release"
    git push <YOUR FORK>
  2. Once the PR is merged to main or release branch (<BRANCH NAME> below), tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  3. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/eraser and ghcr.io/eraser-dev/eraser-manager images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
- - +
Version: v0.5.x

Releasing

Overview

+

The release process consists of three phases: versioning, building, and publishing.

+

Versioning involves maintaining the following files:

+
    +
  • Makefile - the Makefile contains a VERSION variable that defines the version of the project.
  • +
  • manager.yaml - the controller-manager deployment yaml contains the latest release tag image of the project.
  • +
  • eraser.yaml - the eraser.yaml contains all eraser resources to be deployed to a cluster including the latest release tag image of the project.
  • +
+

The steps below explain how to update these files. In addition, the repository should be tagged with the semantic version identifying the release.

+

Building involves obtaining a copy of the repository and triggering a build as part of the GitHub Actions CI pipeline.

+

Publishing involves creating a release tag and creating a new Release on GitHub.

+

Versioning

+
    +
  1. +

    Obtain a copy of the repository.

    +
    git clone git@github.com:eraser-dev/eraser.git
    +
  2. +
  3. +

    If this is a patch release for a release branch, check out applicable branch, such as release-0.1. If not, branch should be main

    +
  4. +
  5. +

    Execute the release-patch target to generate patch. Give the semantic version of the release:

    +
    make release-manifest NEWVERSION=vX.Y.Z
    +
  6. +
  7. +

    Promote staging manifest to release.

    +
    make promote-staging-manifest
    +
  8. +
  9. +

    If it's a new minor release (e.g. v0.4.x -> 0.5.0), tag docs to be versioned. Make sure to keep patch version as .x for a minor release.

    +
    make version-docs NEWVERSION=v0.5.x
    +
  10. +
  11. +

    Preview the changes:

    +
    git status
    git diff
    +
  12. +
+

Building and releasing

+
    +
  1. +

    Commit the changes and push to remote repository to create a pull request.

    +
    git checkout -b release-<NEW VERSION>
    git commit -a -s -m "Prepare <NEW VERSION> release"
    git push <YOUR FORK>
    +
  2. +
  3. +

    Once the PR is merged to main or release branch (<BRANCH NAME> below), tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  4. +
  5. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/eraser and ghcr.io/eraser-dev/eraser-manager images automatically, then publish the new release tag.

    +
  6. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
\ No newline at end of file diff --git a/docs/v0.5.x/setup.html b/docs/v0.5.x/setup.html index cb1c50e50a..b05461d6d2 100644 --- a/docs/v0.5.x/setup.html +++ b/docs/v0.5.x/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: v0.5.x

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-eraser ERASER_IMG=eraser:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
eraser:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
ERASER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
ERASER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
ERASER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-eraser

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
ERASER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-eraser

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
ERASER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: v0.5.x

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-eraser ERASER_IMG=eraser:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
eraser:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
ERASER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-eraser
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
ERASER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-eraser
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/v0.5.x/trivy.html b/docs/v0.5.x/trivy.html index 68482500dc..28ae4ae72c 100644 --- a/docs/v0.5.x/trivy.html +++ b/docs/v0.5.x/trivy.html @@ -1,22 +1,26 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: v0.5.x

Trivy

Trivy Provider Options

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:

  • --ignore-unfixed: boolean to report only fixed vulnerabilities (default true)
  • --security-checks: comma-separated list of what security issues to detect (default "vuln")
  • --vuln-type: list of severity levels to report (default "CRITICAL")
  • --delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)
- - +
Version: v0.5.x

Trivy

Trivy Provider Options

+

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. The following arguments can be supplied to the scanner to specify which types of images will be detected for removal by the trivy scanner container:

+
    +
  • --ignore-unfixed: boolean to report only fixed vulnerabilities (default true)
  • +
  • --security-checks: comma-separated list of what security issues to detect (default "vuln")
  • +
  • --vuln-type: list of severity levels to report (default "CRITICAL")
  • +
  • --delete-scan-failed-images : boolean to delete images for which scanning has failed (default true)
  • +
\ No newline at end of file diff --git a/docs/v1.0.x.html b/docs/v1.0.x.html index cbc31279d5..34225a5393 100644 --- a/docs/v1.0.x.html +++ b/docs/v1.0.x.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: v1.0.x

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: v1.0.x

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/v1.0.x/architecture.html b/docs/v1.0.x/architecture.html index 544e6d34a8..518e80efea 100644 --- a/docs/v1.0.x/architecture.html +++ b/docs/v1.0.x/architecture.html @@ -1,27 +1,30 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Version: v1.0.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: v1.0.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/v1.0.x/code-of-conduct.html b/docs/v1.0.x/code-of-conduct.html index 6c4fdb4d3a..e172ad5e33 100644 --- a/docs/v1.0.x/code-of-conduct.html +++ b/docs/v1.0.x/code-of-conduct.html @@ -1,22 +1,24 @@ - + - -Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v1.0.x/contributing.html b/docs/v1.0.x/contributing.html index a7f07c431c..6db227d9a8 100644 --- a/docs/v1.0.x/contributing.html +++ b/docs/v1.0.x/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v1.0.x/custom-scanner.html b/docs/v1.0.x/custom-scanner.html index 08d7fb0377..bff1820f3d 100644 --- a/docs/v1.0.x/custom-scanner.html +++ b/docs/v1.0.x/custom-scanner.html @@ -1,22 +1,23 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: v1.0.x

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, use the following template.

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

When complete, provide your custom scanner image to Eraser in deployment.

- - +
Version: v1.0.x

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, use the following template.

+

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

+

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

+

When complete, provide your custom scanner image to Eraser in deployment.

\ No newline at end of file diff --git a/docs/v1.0.x/customization.html b/docs/v1.0.x/customization.html index 0890a81ca1..059e3f2bff 100644 --- a/docs/v1.0.x/customization.html +++ b/docs/v1.0.x/customization.html @@ -1,56 +1,95 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: v1.0.x

Customization

Overview

Eraser uses a configmap to configure its behavior. The configmap is part of the +

Version: v1.0.x

Customization

Overview

+

Eraser uses a configmap to configure its behavior. The configmap is part of the deployment and it is not necessary to deploy it manually. Once deployed, the configmap -can be edited at any time:

kubectl edit configmap --namespace eraser-system eraser-manager-config

If an eraser job is already running, the changes will not take effect until the job completes. -The configuration is in yaml.

Key Concepts

Basic architecture

The manager runs as a pod in your cluster and manages ImageJobs. Think of +can be edited at any time:

+
kubectl edit configmap --namespace eraser-system eraser-manager-config
+

If an eraser job is already running, the changes will not take effect until the job completes. +The configuration is in yaml.

+

Key Concepts

+

Basic architecture

+

The manager runs as a pod in your cluster and manages ImageJobs. Think of an ImageJob as a unit of work, performed on every node in your cluster. Each node runs a sub-job. The goal of the ImageJob is to assess the images on your -cluster's nodes, and to remove the images you don't want. There are two stages:

  1. Assessment
  2. Removal.

Scheduling

An ImageJob can either be created on-demand (see Manual Removal), +cluster's nodes, and to remove the images you don't want. There are two stages:

+
    +
  1. Assessment
  2. +
  3. Removal.
  4. +
+

Scheduling

+

An ImageJob can either be created on-demand (see Manual Removal), or they can be spawned on a timer like a cron job. On-demand jobs skip the assessment stage and get right down to the business of removing the images you specified. The behavior of an on-demand job is quite different from that of -timed jobs.

Fault Tolerance

Because an ImageJob runs on every node in your cluster, and the conditions on +timed jobs.

+

Fault Tolerance

+

Because an ImageJob runs on every node in your cluster, and the conditions on each node may vary widely, some of the sub-jobs may fail. If you cannot tolerate any failure, set the manager.imageJob.successRatio property to 1.0. If 75% success sounds good to you, set it to 0.75. In that case, if fewer than 75% of the pods spawned by the ImageJob report success, the job as -a whole will be marked as a failure.

This is mainly to help diagnose error conditions. As such, you can set +a whole will be marked as a failure.

+

This is mainly to help diagnose error conditions. As such, you can set manager.imageJob.cleanup.delayOnFailure to a long value so that logs can be -captured before the spawned pods are cleaned up.

Excluding Nodes

For various reasons, you may want to prevent Eraser from scheduling pods on +captured before the spawned pods are cleaned up.

+

Excluding Nodes

+

For various reasons, you may want to prevent Eraser from scheduling pods on certain nodes. To do so, the nodes can be given a special label. By default, this label is eraser.sh/cleanup.filter, but you can configure the behavior with -the options under manager.nodeFilter. The table provides more detail.

Configuring Components

An ImageJob is made up of various sub-jobs, with one sub-job for each node. -These sub-jobs can be broken down further into three stages.

  1. Collection (What is on the node?)
  2. Scanning (What images conform to the policy I've provided?)
  3. Removal (Remove images based on the results of the above)

Of the above stages, only Removal is mandatory. The others can be disabled. +the options under manager.nodeFilter. The table provides more detail.

+

Configuring Components

+

An ImageJob is made up of various sub-jobs, with one sub-job for each node. +These sub-jobs can be broken down further into three stages.

+
    +
  1. Collection (What is on the node?)
  2. +
  3. Scanning (What images conform to the policy I've provided?)
  4. +
  5. Removal (Remove images based on the results of the above)
  6. +
+

Of the above stages, only Removal is mandatory. The others can be disabled. Furthermore, manually triggered ImageJobs will skip right to removal, even if Eraser is configured to collect and scan. Collection and Scanning will only -take place when:

  1. The collector and/or scanner components are enabled, AND
  2. The job was not triggered manually by creating an ImageList.

Swapping out components

The collector, scanner, and eraser components can all be swapped out. This +take place when:

+
    +
  1. The collector and/or scanner components are enabled, AND
  2. +
  3. The job was not triggered manually by creating an ImageList.
  4. +
+

Swapping out components

+

The collector, scanner, and eraser components can all be swapped out. This enables you to build and host the images yourself. In addition, the scanner's behavior can be completely tailored to your needs by swapping out the default image with one of your own. To specify the images, use the components.<component>.image.repo and components.<component>.image.tag, -where <component> is one of collector, scanner, or eraser.

Universal Options

The following portions of the configmap apply no matter how you spawn your +where <component> is one of collector, scanner, or eraser.

+

Universal Options

+

The following portions of the configmap apply no matter how you spawn your ImageJob. The values provided below are the defaults. For more detail on -these options, see the table.

manager:
runtime: containerd
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/eraser
priorityClassName: "" # priority class name for collector/scanner/eraser
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
eraser:
image:
repo: ghcr.io/eraser-dev/eraser
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Component Options

components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
eraser:
image:
repo: ghcr.io/eraser-dev/eraser
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Scanner Options

These options can be provided to components.scanner.config. They will be +these options, see the table.

+
manager:
runtime: containerd
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/eraser
priorityClassName: "" # priority class name for collector/scanner/eraser
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
eraser:
image:
repo: ghcr.io/eraser-dev/eraser
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Component Options

+
components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
eraser:
image:
repo: ghcr.io/eraser-dev/eraser
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Scanner Options

+

These options can be provided to components.scanner.config. They will be passed through as a string to the scanner container and parsed there. If you -want to configure your own scanner, you must provide some way to parse this.

Below are the values recognized by the provided eraser-trivy-scanner image. -Values provided below are the defaults.

cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more invormation
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted

Detailed Options

OptionDescriptionDefault
manager.runtimeThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and eraser containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and eraser containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.eraser.image.repoThe repository containing the eraser image.ghcr.io/eraser-dev/eraser
components.eraser.image.tagThe tag of the eraser image.v1.0.0
components.eraser.request.memThe amount of memory to request for the eraser container.25Mi
components.eraser.request.cpuThe amount of CPU to request for the eraser container.0
- - +want to configure your own scanner, you must provide some way to parse this.

+

Below are the values recognized by the provided eraser-trivy-scanner image. +Values provided below are the defaults.

+
cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more invormation
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted
+

Detailed Options

+
OptionDescriptionDefault
manager.runtimeThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and eraser containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and eraser containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.eraser.image.repoThe repository containing the eraser image.ghcr.io/eraser-dev/eraser
components.eraser.image.tagThe tag of the eraser image.v1.0.0
components.eraser.request.memThe amount of memory to request for the eraser container.25Mi
components.eraser.request.cpuThe amount of CPU to request for the eraser container.0
\ No newline at end of file diff --git a/docs/v1.0.x/exclusion.html b/docs/v1.0.x/exclusion.html index 74cdd93c9a..def8229940 100644 --- a/docs/v1.0.x/exclusion.html +++ b/docs/v1.0.x/exclusion.html @@ -1,22 +1,24 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: v1.0.x

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

- - +
Version: v1.0.x

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

\ No newline at end of file diff --git a/docs/v1.0.x/faq.html b/docs/v1.0.x/faq.html index 51feb56f02..7f96ac236d 100644 --- a/docs/v1.0.x/faq.html +++ b/docs/v1.0.x/faq.html @@ -1,22 +1,20 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: v1.0.x

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

- - +
Version: v1.0.x

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

\ No newline at end of file diff --git a/docs/v1.0.x/installation.html b/docs/v1.0.x/installation.html index 1820bacf57..ddace09f74 100644 --- a/docs/v1.0.x/installation.html +++ b/docs/v1.0.x/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: v1.0.x

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.0.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: v1.0.x

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.0.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/v1.0.x/manual-removal.html b/docs/v1.0.x/manual-removal.html index 008590a89b..c9f3438a28 100644 --- a/docs/v1.0.x/manual-removal.html +++ b/docs/v1.0.x/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: v1.0.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: v1.0.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/v1.0.x/metrics.html b/docs/v1.0.x/metrics.html index 1c5381a114..bfccb4606c 100644 --- a/docs/v1.0.x/metrics.html +++ b/docs/v1.0.x/metrics.html @@ -1,22 +1,26 @@ - + - -Metrics | Eraser Docs + +Metrics | Eraser Docs - - - + + + -
-
Version: v1.0.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

Below is the list of metrics provided by Eraser per run:

Eraser

- count
- name: images_removed_run_total
- description: Total images removed by eraser

Scanner

- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected

ImageJob

- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
- - +
Version: v1.0.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

+

Below is the list of metrics provided by Eraser per run:

+

Eraser

+
- count
- name: images_removed_run_total
- description: Total images removed by eraser
+

Scanner

+
- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected
+

ImageJob

+
- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
\ No newline at end of file diff --git a/docs/v1.0.x/quick-start.html b/docs/v1.0.x/quick-start.html index 7d3b0f4ad4..3a470306b1 100644 --- a/docs/v1.0.x/quick-start.html +++ b/docs/v1.0.x/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: v1.0.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and eraser.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: v1.0.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule collector pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and eraser that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system collector-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system collector-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the eraser container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and eraser.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system collector-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system collector-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system collector-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/v1.0.x/releasing.html b/docs/v1.0.x/releasing.html index f62df2b89a..d72b25d298 100644 --- a/docs/v1.0.x/releasing.html +++ b/docs/v1.0.x/releasing.html @@ -1,23 +1,40 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: v1.0.x

Releasing

Create Release Pull Request

  1. Go to create_release_pull_request workflow under actions.
  2. Select run workflow, and use the workflow from your branch.
  3. Input release version with the semantic version identifying the release.
  4. Click run workflow and review the PR created by github-actions.

Releasing

  1. Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  2. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/eraser, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
- - +
Version: v1.0.x

Releasing

Create Release Pull Request

+
    +
  1. Go to create_release_pull_request workflow under actions.
  2. +
  3. Select run workflow, and use the workflow from your branch.
  4. +
  5. Input release version with the semantic version identifying the release.
  6. +
  7. Click run workflow and review the PR created by github-actions.
  8. +
+

Releasing

+
    +
  1. +

    Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  2. +
  3. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/eraser, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

    +
  4. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
\ No newline at end of file diff --git a/docs/v1.0.x/setup.html b/docs/v1.0.x/setup.html index d2969e826b..8be32f1628 100644 --- a/docs/v1.0.x/setup.html +++ b/docs/v1.0.x/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: v1.0.x

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-eraser ERASER_IMG=eraser:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
eraser:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
ERASER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
ERASER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
ERASER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-eraser

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
ERASER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-eraser

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
ERASER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: v1.0.x

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-eraser ERASER_IMG=eraser:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
eraser:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
ERASER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-eraser
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
ERASER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-eraser
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
ERASER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/v1.0.x/trivy.html b/docs/v1.0.x/trivy.html index a78d3f3439..b705ff5e4c 100644 --- a/docs/v1.0.x/trivy.html +++ b/docs/v1.0.x/trivy.html @@ -1,22 +1,20 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: v1.0.x

Trivy

Trivy Provider Options

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

- - +
Version: v1.0.x

Trivy

Trivy Provider Options

+

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

\ No newline at end of file diff --git a/docs/v1.1.x.html b/docs/v1.1.x.html index 253a23cb5f..10f20dc5b5 100644 --- a/docs/v1.1.x.html +++ b/docs/v1.1.x.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: v1.1.x

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: v1.1.x

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/v1.1.x/architecture.html b/docs/v1.1.x/architecture.html index 9acdb16c19..a42f21bd19 100644 --- a/docs/v1.1.x/architecture.html +++ b/docs/v1.1.x/architecture.html @@ -1,27 +1,30 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Version: v1.1.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: v1.1.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/v1.1.x/code-of-conduct.html b/docs/v1.1.x/code-of-conduct.html index 2ce6ada566..666178e62e 100644 --- a/docs/v1.1.x/code-of-conduct.html +++ b/docs/v1.1.x/code-of-conduct.html @@ -1,22 +1,24 @@ - + - -Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v1.1.x/contributing.html b/docs/v1.1.x/contributing.html index 83c03d4be2..2090e1517b 100644 --- a/docs/v1.1.x/contributing.html +++ b/docs/v1.1.x/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v1.1.x/custom-scanner.html b/docs/v1.1.x/custom-scanner.html index c20c75933e..8400954ef8 100644 --- a/docs/v1.1.x/custom-scanner.html +++ b/docs/v1.1.x/custom-scanner.html @@ -1,22 +1,23 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: v1.1.x

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, use the following template.

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

When complete, provide your custom scanner image to Eraser in deployment.

- - +
Version: v1.1.x

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, use the following template.

+

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

+

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

+

When complete, provide your custom scanner image to Eraser in deployment.

\ No newline at end of file diff --git a/docs/v1.1.x/customization.html b/docs/v1.1.x/customization.html index b0ec3085d3..403a15b075 100644 --- a/docs/v1.1.x/customization.html +++ b/docs/v1.1.x/customization.html @@ -1,56 +1,95 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: v1.1.x

Customization

Overview

Eraser uses a configmap to configure its behavior. The configmap is part of the +

Version: v1.1.x

Customization

Overview

+

Eraser uses a configmap to configure its behavior. The configmap is part of the deployment and it is not necessary to deploy it manually. Once deployed, the configmap -can be edited at any time:

kubectl edit configmap --namespace eraser-system eraser-manager-config

If an eraser job is already running, the changes will not take effect until the job completes. -The configuration is in yaml.

Key Concepts

Basic architecture

The manager runs as a pod in your cluster and manages ImageJobs. Think of +can be edited at any time:

+
kubectl edit configmap --namespace eraser-system eraser-manager-config
+

If an eraser job is already running, the changes will not take effect until the job completes. +The configuration is in yaml.

+

Key Concepts

+

Basic architecture

+

The manager runs as a pod in your cluster and manages ImageJobs. Think of an ImageJob as a unit of work, performed on every node in your cluster. Each node runs a sub-job. The goal of the ImageJob is to assess the images on your -cluster's nodes, and to remove the images you don't want. There are two stages:

  1. Assessment
  2. Removal.

Scheduling

An ImageJob can either be created on-demand (see Manual Removal), +cluster's nodes, and to remove the images you don't want. There are two stages:

+
    +
  1. Assessment
  2. +
  3. Removal.
  4. +
+

Scheduling

+

An ImageJob can either be created on-demand (see Manual Removal), or they can be spawned on a timer like a cron job. On-demand jobs skip the assessment stage and get right down to the business of removing the images you specified. The behavior of an on-demand job is quite different from that of -timed jobs.

Fault Tolerance

Because an ImageJob runs on every node in your cluster, and the conditions on +timed jobs.

+

Fault Tolerance

+

Because an ImageJob runs on every node in your cluster, and the conditions on each node may vary widely, some of the sub-jobs may fail. If you cannot tolerate any failure, set the manager.imageJob.successRatio property to 1.0. If 75% success sounds good to you, set it to 0.75. In that case, if fewer than 75% of the pods spawned by the ImageJob report success, the job as -a whole will be marked as a failure.

This is mainly to help diagnose error conditions. As such, you can set +a whole will be marked as a failure.

+

This is mainly to help diagnose error conditions. As such, you can set manager.imageJob.cleanup.delayOnFailure to a long value so that logs can be -captured before the spawned pods are cleaned up.

Excluding Nodes

For various reasons, you may want to prevent Eraser from scheduling pods on +captured before the spawned pods are cleaned up.

+

Excluding Nodes

+

For various reasons, you may want to prevent Eraser from scheduling pods on certain nodes. To do so, the nodes can be given a special label. By default, this label is eraser.sh/cleanup.filter, but you can configure the behavior with -the options under manager.nodeFilter. The table provides more detail.

Configuring Components

An ImageJob is made up of various sub-jobs, with one sub-job for each node. -These sub-jobs can be broken down further into three stages.

  1. Collection (What is on the node?)
  2. Scanning (What images conform to the policy I've provided?)
  3. Removal (Remove images based on the results of the above)

Of the above stages, only Removal is mandatory. The others can be disabled. +the options under manager.nodeFilter. The table provides more detail.

+

Configuring Components

+

An ImageJob is made up of various sub-jobs, with one sub-job for each node. +These sub-jobs can be broken down further into three stages.

+
    +
  1. Collection (What is on the node?)
  2. +
  3. Scanning (What images conform to the policy I've provided?)
  4. +
  5. Removal (Remove images based on the results of the above)
  6. +
+

Of the above stages, only Removal is mandatory. The others can be disabled. Furthermore, manually triggered ImageJobs will skip right to removal, even if Eraser is configured to collect and scan. Collection and Scanning will only -take place when:

  1. The collector and/or scanner components are enabled, AND
  2. The job was not triggered manually by creating an ImageList.

Swapping out components

The collector, scanner, and remover components can all be swapped out. This +take place when:

+
    +
  1. The collector and/or scanner components are enabled, AND
  2. +
  3. The job was not triggered manually by creating an ImageList.
  4. +
+

Swapping out components

+

The collector, scanner, and remover components can all be swapped out. This enables you to build and host the images yourself. In addition, the scanner's behavior can be completely tailored to your needs by swapping out the default image with one of your own. To specify the images, use the components.<component>.image.repo and components.<component>.image.tag, -where <component> is one of collector, scanner, or remover.

Universal Options

The following portions of the configmap apply no matter how you spawn your +where <component> is one of collector, scanner, or remover.

+

Universal Options

+

The following portions of the configmap apply no matter how you spawn your ImageJob. The values provided below are the defaults. For more detail on -these options, see the table.

manager:
runtime: containerd
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Component Options

components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Scanner Options

These options can be provided to components.scanner.config. They will be +these options, see the table.

+
manager:
runtime: containerd
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Component Options

+
components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Scanner Options

+

These options can be provided to components.scanner.config. They will be passed through as a string to the scanner container and parsed there. If you -want to configure your own scanner, you must provide some way to parse this.

Below are the values recognized by the provided eraser-trivy-scanner image. -Values provided below are the defaults.

cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more invormation
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted

Detailed Options

OptionDescriptionDefault
manager.runtimeThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
- - +want to configure your own scanner, you must provide some way to parse this.

+

Below are the values recognized by the provided eraser-trivy-scanner image. +Values provided below are the defaults.

+
cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more invormation
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted
+

Detailed Options

+
OptionDescriptionDefault
manager.runtimeThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
\ No newline at end of file diff --git a/docs/v1.1.x/exclusion.html b/docs/v1.1.x/exclusion.html index 0cf8ef6ba3..8d8adb46ba 100644 --- a/docs/v1.1.x/exclusion.html +++ b/docs/v1.1.x/exclusion.html @@ -1,22 +1,24 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: v1.1.x

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

- - +
Version: v1.1.x

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

\ No newline at end of file diff --git a/docs/v1.1.x/faq.html b/docs/v1.1.x/faq.html index aed57abb55..925867b800 100644 --- a/docs/v1.1.x/faq.html +++ b/docs/v1.1.x/faq.html @@ -1,22 +1,27 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: v1.1.x

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

How is Eraser different from Kubernetes garbage collection?

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

There are a couple core benefits to using Eraser for image cleanup:

  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
- - +
Version: v1.1.x

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

+

How is Eraser different from Kubernetes garbage collection?

+

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

+

There are a couple core benefits to using Eraser for image cleanup:

+
    +
  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • +
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
  • +
\ No newline at end of file diff --git a/docs/v1.1.x/installation.html b/docs/v1.1.x/installation.html index 0a92bc1c2c..d6ff14e44c 100644 --- a/docs/v1.1.x/installation.html +++ b/docs/v1.1.x/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: v1.1.x

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: v1.1.x

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.1.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/v1.1.x/manual-removal.html b/docs/v1.1.x/manual-removal.html index 6a01026824..bc85278633 100644 --- a/docs/v1.1.x/manual-removal.html +++ b/docs/v1.1.x/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: v1.1.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: v1.1.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/v1.1.x/metrics.html b/docs/v1.1.x/metrics.html index d851dfb3e5..3a1c496ead 100644 --- a/docs/v1.1.x/metrics.html +++ b/docs/v1.1.x/metrics.html @@ -1,22 +1,26 @@ - + - -Metrics | Eraser Docs + +Metrics | Eraser Docs - - - + + + -
-
Version: v1.1.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

Below is the list of metrics provided by Eraser per run:

Eraser

- count
- name: images_removed_run_total
- description: Total images removed by eraser

Scanner

- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected

ImageJob

- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
- - +
Version: v1.1.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

+

Below is the list of metrics provided by Eraser per run:

+

Eraser

+
- count
- name: images_removed_run_total
- description: Total images removed by eraser
+

Scanner

+
- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected
+

ImageJob

+
- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
\ No newline at end of file diff --git a/docs/v1.1.x/quick-start.html b/docs/v1.1.x/quick-start.html index 96f660525c..54b12b53c3 100644 --- a/docs/v1.1.x/quick-start.html +++ b/docs/v1.1.x/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: v1.1.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: v1.1.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/v1.1.x/releasing.html b/docs/v1.1.x/releasing.html index 1121ffb08c..7ef43ce391 100644 --- a/docs/v1.1.x/releasing.html +++ b/docs/v1.1.x/releasing.html @@ -1,23 +1,40 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: v1.1.x

Releasing

Create Release Pull Request

  1. Go to create_release_pull_request workflow under actions.
  2. Select run workflow, and use the workflow from your branch.
  3. Input release version with the semantic version identifying the release.
  4. Click run workflow and review the PR created by github-actions.

Releasing

  1. Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  2. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
- - +
Version: v1.1.x

Releasing

Create Release Pull Request

+
    +
  1. Go to create_release_pull_request workflow under actions.
  2. +
  3. Select run workflow, and use the workflow from your branch.
  4. +
  5. Input release version with the semantic version identifying the release.
  6. +
  7. Click run workflow and review the PR created by github-actions.
  8. +
+

Releasing

+
    +
  1. +

    Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  2. +
  3. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

    +
  4. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
\ No newline at end of file diff --git a/docs/v1.1.x/setup.html b/docs/v1.1.x/setup.html index 742933013d..dbacb39459 100644 --- a/docs/v1.1.x/setup.html +++ b/docs/v1.1.x/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: v1.1.x

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-remover

Builds the docker image for eraser remover.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-remover

Builds the docker image for the eraser remover.

Configuration Options:

Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: v1.1.x

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-remover
  • +
+

Builds the docker image for eraser remover.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-remover
  • +
+

Builds the docker image for the eraser remover.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/v1.1.x/trivy.html b/docs/v1.1.x/trivy.html index 9a8d6f7962..f821c9d790 100644 --- a/docs/v1.1.x/trivy.html +++ b/docs/v1.1.x/trivy.html @@ -1,22 +1,20 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: v1.1.x

Trivy

Trivy Provider Options

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

- - +
Version: v1.1.x

Trivy

Trivy Provider Options

+

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

\ No newline at end of file diff --git a/docs/v1.2.x.html b/docs/v1.2.x.html index 2e8c5599d5..2714eb328e 100644 --- a/docs/v1.2.x.html +++ b/docs/v1.2.x.html @@ -1,22 +1,21 @@ - + - -Introduction | Eraser Docs + +Introduction | Eraser Docs - - - + + + -
-
Version: v1.2.x

Introduction

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

- - +
Version: v1.2.x

Introduction

+

When deploying to Kubernetes, it's common for pipelines to build and push images to a cluster, but it's much less common for these images to be cleaned up. This can lead to accumulating bloat on the disk, and a host of non-compliant images lingering on the nodes.

+

The current garbage collection process deletes images based on a percentage of load, but this process does not consider the vulnerability state of the images. Eraser aims to provide a simple way to determine the state of an image, and delete it if it meets the specified criteria.

\ No newline at end of file diff --git a/docs/v1.2.x/architecture.html b/docs/v1.2.x/architecture.html index 9104076e47..ba59c30c95 100644 --- a/docs/v1.2.x/architecture.html +++ b/docs/v1.2.x/architecture.html @@ -1,27 +1,30 @@ - + - -Architecture | Eraser Docs + +Architecture | Eraser Docs - - - + + + -
-
Version: v1.2.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

Manual image removal involves supplying a list of images to remove; Eraser then -deploys pods to clean up the images you supplied.

Automated image removal runs on a timer. By default, the automated process +

Version: v1.2.x

Architecture

At a high level, Eraser has two main modes of operation: manual and automated.

+

Manual image removal involves supplying a list of images to remove; Eraser then +deploys pods to clean up the images you supplied.

+

Automated image removal runs on a timer. By default, the automated process removes images based on the results of a vulnerability scan. The default vulnerability scanner is Trivy, but others can be provided in its place. Or, the scanner can be disabled altogether, in which case Eraser acts as a garbage -collector -- it will remove all non-running images in your cluster.

Manual image cleanup

Automated analysis, scanning, and cleanup

- - +collector -- it will remove all non-running images in your cluster.

+

Manual image cleanup

+ +

Automated analysis, scanning, and cleanup

+
\ No newline at end of file diff --git a/docs/v1.2.x/code-of-conduct.html b/docs/v1.2.x/code-of-conduct.html index 48d67ac99a..5d86e0231d 100644 --- a/docs/v1.2.x/code-of-conduct.html +++ b/docs/v1.2.x/code-of-conduct.html @@ -1,22 +1,24 @@ - + - -Code of Conduct | Eraser Docs + +Code of Conduct | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v1.2.x/contributing.html b/docs/v1.2.x/contributing.html index 86c93ff34c..8be72ce5c0 100644 --- a/docs/v1.2.x/contributing.html +++ b/docs/v1.2.x/contributing.html @@ -1,22 +1,27 @@ - + - -Contributing | Eraser Docs + +Contributing | Eraser Docs - - - + + + -
-
- - +
\ No newline at end of file diff --git a/docs/v1.2.x/custom-scanner.html b/docs/v1.2.x/custom-scanner.html index 846863686a..061113882f 100644 --- a/docs/v1.2.x/custom-scanner.html +++ b/docs/v1.2.x/custom-scanner.html @@ -1,22 +1,23 @@ - + - -Custom Scanner | Eraser Docs + +Custom Scanner | Eraser Docs - - - + + + -
-
Version: v1.2.x

Custom Scanner

Creating a Custom Scanner

To create a custom scanner for non-compliant images, use the following template.

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

When complete, provide your custom scanner image to Eraser in deployment.

- - +
Version: v1.2.x

Custom Scanner

Creating a Custom Scanner

+

To create a custom scanner for non-compliant images, use the following template.

+

In order to customize your scanner, start by creating a NewImageProvider(). The ImageProvider interface can be found can be found here.

+

The ImageProvider will allow you to retrieve the list of all non-running and non-excluded images from the collector container through the ReceiveImages() function. Process these images with your customized scanner and threshold, and use SendImages() to pass the images found non-compliant to the eraser container for removal. Finally, complete the scanning process by calling Finish().

+

When complete, provide your custom scanner image to Eraser in deployment.

\ No newline at end of file diff --git a/docs/v1.2.x/customization.html b/docs/v1.2.x/customization.html index 18e19b7e87..0303d26f86 100644 --- a/docs/v1.2.x/customization.html +++ b/docs/v1.2.x/customization.html @@ -1,56 +1,95 @@ - + - -Customization | Eraser Docs + +Customization | Eraser Docs - - - + + + -
-
Version: v1.2.x

Customization

Overview

Eraser uses a configmap to configure its behavior. The configmap is part of the +

Version: v1.2.x

Customization

Overview

+

Eraser uses a configmap to configure its behavior. The configmap is part of the deployment and it is not necessary to deploy it manually. Once deployed, the configmap -can be edited at any time:

kubectl edit configmap --namespace eraser-system eraser-manager-config

If an eraser job is already running, the changes will not take effect until the job completes. -The configuration is in yaml.

Key Concepts

Basic architecture

The manager runs as a pod in your cluster and manages ImageJobs. Think of +can be edited at any time:

+
kubectl edit configmap --namespace eraser-system eraser-manager-config
+

If an eraser job is already running, the changes will not take effect until the job completes. +The configuration is in yaml.

+

Key Concepts

+

Basic architecture

+

The manager runs as a pod in your cluster and manages ImageJobs. Think of an ImageJob as a unit of work, performed on every node in your cluster. Each node runs a sub-job. The goal of the ImageJob is to assess the images on your -cluster's nodes, and to remove the images you don't want. There are two stages:

  1. Assessment
  2. Removal.

Scheduling

An ImageJob can either be created on-demand (see Manual Removal), +cluster's nodes, and to remove the images you don't want. There are two stages:

+
    +
  1. Assessment
  2. +
  3. Removal.
  4. +
+

Scheduling

+

An ImageJob can either be created on-demand (see Manual Removal), or they can be spawned on a timer like a cron job. On-demand jobs skip the assessment stage and get right down to the business of removing the images you specified. The behavior of an on-demand job is quite different from that of -timed jobs.

Fault Tolerance

Because an ImageJob runs on every node in your cluster, and the conditions on +timed jobs.

+

Fault Tolerance

+

Because an ImageJob runs on every node in your cluster, and the conditions on each node may vary widely, some of the sub-jobs may fail. If you cannot tolerate any failure, set the manager.imageJob.successRatio property to 1.0. If 75% success sounds good to you, set it to 0.75. In that case, if fewer than 75% of the pods spawned by the ImageJob report success, the job as -a whole will be marked as a failure.

This is mainly to help diagnose error conditions. As such, you can set +a whole will be marked as a failure.

+

This is mainly to help diagnose error conditions. As such, you can set manager.imageJob.cleanup.delayOnFailure to a long value so that logs can be -captured before the spawned pods are cleaned up.

Excluding Nodes

For various reasons, you may want to prevent Eraser from scheduling pods on +captured before the spawned pods are cleaned up.

+

Excluding Nodes

+

For various reasons, you may want to prevent Eraser from scheduling pods on certain nodes. To do so, the nodes can be given a special label. By default, this label is eraser.sh/cleanup.filter, but you can configure the behavior with -the options under manager.nodeFilter. The table provides more detail.

Configuring Components

An ImageJob is made up of various sub-jobs, with one sub-job for each node. -These sub-jobs can be broken down further into three stages.

  1. Collection (What is on the node?)
  2. Scanning (What images conform to the policy I've provided?)
  3. Removal (Remove images based on the results of the above)

Of the above stages, only Removal is mandatory. The others can be disabled. +the options under manager.nodeFilter. The table provides more detail.

+

Configuring Components

+

An ImageJob is made up of various sub-jobs, with one sub-job for each node. +These sub-jobs can be broken down further into three stages.

+
    +
  1. Collection (What is on the node?)
  2. +
  3. Scanning (What images conform to the policy I've provided?)
  4. +
  5. Removal (Remove images based on the results of the above)
  6. +
+

Of the above stages, only Removal is mandatory. The others can be disabled. Furthermore, manually triggered ImageJobs will skip right to removal, even if Eraser is configured to collect and scan. Collection and Scanning will only -take place when:

  1. The collector and/or scanner components are enabled, AND
  2. The job was not triggered manually by creating an ImageList.

Swapping out components

The collector, scanner, and remover components can all be swapped out. This +take place when:

+
    +
  1. The collector and/or scanner components are enabled, AND
  2. +
  3. The job was not triggered manually by creating an ImageList.
  4. +
+

Swapping out components

+

The collector, scanner, and remover components can all be swapped out. This enables you to build and host the images yourself. In addition, the scanner's behavior can be completely tailored to your needs by swapping out the default image with one of your own. To specify the images, use the components.<component>.image.repo and components.<component>.image.tag, -where <component> is one of collector, scanner, or remover.

Universal Options

The following portions of the configmap apply no matter how you spawn your +where <component> is one of collector, scanner, or remover.

+

Universal Options

+

The following portions of the configmap apply no matter how you spawn your ImageJob. The values provided below are the defaults. For more detail on -these options, see the table.

manager:
runtime: containerd
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Component Options

components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m

Scanner Options

These options can be provided to components.scanner.config. They will be +these options, see the table.

+
manager:
runtime: containerd
otlpEndpoint: "" # empty string disables OpenTelemetry
logLevel: info
profile:
enabled: false
port: 6060
imageJob:
successRatio: 1.0
cleanup:
delayOnSuccess: 0s
delayOnFailure: 24h
pullSecrets: [] # image pull secrets for collector/scanner/remover
priorityClassName: "" # priority class name for collector/scanner/remover
nodeFilter:
type: exclude # must be either exclude|include
selectors:
- eraser.sh/cleanup.filter
- kubernetes.io/os=windows
components:
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Component Options

+
components:
collector:
enabled: true
image:
repo: ghcr.io/eraser-dev/collector
tag: v1.0.0
request:
mem: 25Mi
cpu: 7m
limit:
mem: 500Mi
cpu: 0
scanner:
enabled: true
image:
repo: ghcr.io/eraser-dev/eraser-trivy-scanner
tag: v1.0.0
request:
mem: 500Mi
cpu: 1000m
limit:
mem: 2Gi
cpu: 0
config: |
# this is the schema for the provided 'trivy-scanner'. custom scanners
# will define their own configuration. see the below
remover:
image:
repo: ghcr.io/eraser-dev/remover
tag: v1.0.0
request:
mem: 25Mi
cpu: 0
limit:
mem: 30Mi
cpu: 1000m
+

Scanner Options

+

These options can be provided to components.scanner.config. They will be passed through as a string to the scanner container and parsed there. If you -want to configure your own scanner, you must provide some way to parse this.

Below are the values recognized by the provided eraser-trivy-scanner image. -Values provided below are the defaults.

cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more invormation
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted

Detailed Options

OptionDescriptionDefault
manager.runtimeThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
- - +want to configure your own scanner, you must provide some way to parse this.

+

Below are the values recognized by the provided eraser-trivy-scanner image. +Values provided below are the defaults.

+
cacheDir: /var/lib/trivy # The file path inside the container to store the cache
dbRepo: ghcr.io/aquasecurity/trivy-db # The container registry from which to fetch the trivy database
deleteFailedImages: true # if true, remove images for which scanning fails, regardless of why it failed
deleteEOLImages: true # if true, remove images that have reached their end-of-life date
vulnerabilities:
ignoreUnfixed: true # consider the image compliant if there are no known fixes for the vulnerabilities found.
types: # a list of vulnerability types. for more info, see trivy's documentation.
- os
- library
securityChecks: # see trivy's documentation for more invormation
- vuln
severities: # in this case, only flag images with CRITICAL vulnerability for removal
- CRITICAL
timeout:
total: 23h # if scanning isn't completed before this much time elapses, abort the whole scan
perImage: 1h # if scanning a single image exceeds this time, scanning will be aborted
+

Detailed Options

+
OptionDescriptionDefault
manager.runtimeThe runtime to use for the manager's containers. Must be one of containerd, crio, or dockershim. It is assumed that your nodes are all using the same runtime, and there is currently no way to configure multiple runtimes.containerd
manager.otlpEndpointThe endpoint to send OpenTelemetry data to. If empty, data will not be sent.""
manager.logLevelThe log level for the manager's containers. Must be one of debug, info, warn, error, dpanic, panic, or fatal.info
manager.scheduling.repeatIntervalUse only when collector ando/or scanner are enabled. This is like a cron job, and will spawn an ImageJob at the interval provided.24h
manager.scheduling.beginImmediatelyIf set to true, the fist ImageJob will run immediately. If false, the job will not be spawned until after the interval (above) has elapsed.true
manager.profile.enabledWhether to enable profiling for the manager's containers. This is for debugging with go tool pprof.false
manager.profile.portThe port on which to expose the profiling endpoint.6060
manager.imageJob.successRatioThe ratio of successful image jobs required before a cleanup is performed.1.0
manager.imageJob.cleanup.delayOnSuccessThe amount of time to wait after a successful image job before performing cleanup.0s
manager.imageJob.cleanup.delayOnFailureThe amount of time to wait after a failed image job before performing cleanup.24h
manager.pullSecretsThe image pull secrets to use for collector, scanner, and remover containers.[]
manager.priorityClassNameThe priority class to use for collector, scanner, and remover containers.""
manager.nodeFilter.typeThe type of node filter to use. Must be either "exclude" or "include".exclude
manager.nodeFilter.selectorsA list of selectors used to filter nodes.[]
components.collector.enabledWhether to enable the collector component.true
components.collector.image.repoThe repository containing the collector image.ghcr.io/eraser-dev/collector
components.collector.image.tagThe tag of the collector image.v1.0.0
components.collector.request.memThe amount of memory to request for the collector container.25Mi
components.collector.request.cpuThe amount of CPU to request for the collector container.7m
components.collector.limit.memThe maximum amount of memory the collector container is allowed to use.500Mi
components.collector.limit.cpuThe maximum amount of CPU the collector container is allowed to use.0
components.scanner.enabledWhether to enable the scanner component.true
components.scanner.image.repoThe repository containing the scanner image.ghcr.io/eraser-dev/eraser-trivy-scanner
components.scanner.image.tagThe tag of the scanner image.v1.0.0
components.scanner.request.memThe amount of memory to request for the scanner container.500Mi
components.scanner.request.cpuThe amount of CPU to request for the scanner container.1000m
components.scanner.limit.memThe maximum amount of memory the scanner container is allowed to use.2Gi
components.scanner.limit.cpuThe maximum amount of CPU the scanner container is allowed to use.0
components.scanner.configThe configuration to pass to the scanner container, as a YAML string.See YAML below
components.remover.image.repoThe repository containing the remover image.ghcr.io/eraser-dev/remover
components.remover.image.tagThe tag of the remover image.v1.0.0
components.remover.request.memThe amount of memory to request for the remover container.25Mi
components.remover.request.cpuThe amount of CPU to request for the remover container.0
\ No newline at end of file diff --git a/docs/v1.2.x/exclusion.html b/docs/v1.2.x/exclusion.html index 7d7628a721..1c85805572 100644 --- a/docs/v1.2.x/exclusion.html +++ b/docs/v1.2.x/exclusion.html @@ -1,22 +1,24 @@ - + - -Exclusion | Eraser Docs + +Exclusion | Eraser Docs - - - + + + -
-
Version: v1.2.x

Exclusion

Excluding registries, repositories, and images

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system

Exempting Nodes from the Eraser Pipeline

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

- - +
Version: v1.2.x

Exclusion

Excluding registries, repositories, and images

+

Eraser can exclude registries (example, docker.io/library/*) and also specific images with a tag (example, docker.io/library/ubuntu:18.04) or digest (example, sha256:80f31da1ac7b312ba29d65080fd...) from its removal process.

+

To exclude any images or registries from the removal, create configmap(s) with the label eraser.sh/exclude.list=true in the eraser-system namespace with a JSON file holding the excluded images.

+
$ cat > sample.json <<"EOF"
{
"excluded": [
"docker.io/library/*",
"ghcr.io/eraser-dev/test:latest"
]
}
EOF

$ kubectl create configmap excluded --from-file=sample.json --namespace=eraser-system
$ kubectl label configmap excluded eraser.sh/exclude.list=true -n eraser-system
+

Exempting Nodes from the Eraser Pipeline

+

Exempting nodes from cleanup was added in v1.0.0. When deploying Eraser, you can specify whether there is a list of nodes you would like to include or exclude from the cleanup process using the configmap. For more information, see the section on customization.

\ No newline at end of file diff --git a/docs/v1.2.x/faq.html b/docs/v1.2.x/faq.html index a354496e14..a484592edd 100644 --- a/docs/v1.2.x/faq.html +++ b/docs/v1.2.x/faq.html @@ -1,22 +1,27 @@ - + - -FAQ | Eraser Docs + +FAQ | Eraser Docs - - - + + + -
-
Version: v1.2.x

FAQ

Why am I still seeing vulnerable images?

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

How is Eraser different from Kubernetes garbage collection?

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

There are a couple core benefits to using Eraser for image cleanup:

  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
- - +
Version: v1.2.x

FAQ

Why am I still seeing vulnerable images?

+

Eraser currently targets non-running images, so any vulnerable images that are currently running will not be removed. In addition, the default vulnerability scanning with Trivy removes images with CRITICAL vulnerabilities. Any images with lower vulnerabilities will not be removed. This can be configured using the configmap.

+

How is Eraser different from Kubernetes garbage collection?

+

The native garbage collection in Kubernetes works a bit differently than Eraser. By default, garbage collection begins when disk usage reaches 85%, and stops when it gets down to 80%. More details about Kubernetes garbage collection can be found in the Kubernetes documentation, and configuration options can be found in the Kubelet documentation.

+

There are a couple core benefits to using Eraser for image cleanup:

+
    +
  • Eraser can be configured to use image vulnerability data when making determinations on image removal
  • +
  • By interfacing directly with the container runtime, Eraser can clean up images that are not managed by Kubelet and Kubernetes
  • +
\ No newline at end of file diff --git a/docs/v1.2.x/installation.html b/docs/v1.2.x/installation.html index 3ff4e7fa8d..0011c25e91 100644 --- a/docs/v1.2.x/installation.html +++ b/docs/v1.2.x/installation.html @@ -1,22 +1,23 @@ - + - -Installation | Eraser Docs + +Installation | Eraser Docs - - - + + + -
-
Version: v1.2.x

Installation

Manifest

To install Eraser with the manifest file, run the following command:

kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.2.0/deploy/eraser.yaml

Helm

If you'd like to install and manage Eraser with Helm, follow the install instructions here

- - +
Version: v1.2.x

Installation

Manifest

+

To install Eraser with the manifest file, run the following command:

+
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.2.0/deploy/eraser.yaml
+

Helm

+

If you'd like to install and manage Eraser with Helm, follow the install instructions here

\ No newline at end of file diff --git a/docs/v1.2.x/manual-removal.html b/docs/v1.2.x/manual-removal.html index a249e2cc27..3aa32594a0 100644 --- a/docs/v1.2.x/manual-removal.html +++ b/docs/v1.2.x/manual-removal.html @@ -1,22 +1,32 @@ - + - -Manual Removal | Eraser Docs + +Manual Removal | Eraser Docs - - - + + + -
-
Version: v1.2.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s

Pods will run to completion and the images will be removed.

$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...

Verify the unused images are removed.

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine

If the image has been successfully removed, there will be no output.

- - +
Version: v1.2.x

Manual Removal

Create an ImageList and specify the images you would like to remove. In this case, the image docker.io/library/alpine:3.7.3 will be removed.

+
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
name: imagelist
spec:
images:
- docker.io/library/alpine:3.7.3 # use "*" for all non-running images
EOF
+
+

ImageList is a cluster-scoped resource and must be called imagelist. "*" can be specified to remove all non-running images instead of individual images.

+
+

Creating an ImageList should trigger an ImageJob that will deploy Eraser pods on every node to perform the removal given the list of images.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-55d54c4fb6-dcglq 1/1 Running 0 9m8s
eraser-system eraser-kind-control-plane 1/1 Running 0 11s
eraser-system eraser-kind-worker 1/1 Running 0 11s
eraser-system eraser-kind-worker2 1/1 Running 0 11s
+

Pods will run to completion and the images will be removed.

+
$ kubectl get pods -n eraser-system
eraser-system eraser-controller-manager-6d6d5594d4-phl2q 1/1 Running 0 4m16s
eraser-system eraser-kind-control-plane 0/1 Completed 0 22s
eraser-system eraser-kind-worker 0/1 Completed 0 22s
eraser-system eraser-kind-worker2 0/1 Completed 0 22s
+

The ImageList custom resource status field will contain the status of the last job. The success and failure counts indicate the number of nodes the Eraser agent was run on.

+
$ kubectl describe ImageList imagelist
...
Status:
Failed: 0
Success: 3
Timestamp: 2022-02-25T23:41:55Z
...
+

Verify the unused images are removed.

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
+

If the image has been successfully removed, there will be no output.

\ No newline at end of file diff --git a/docs/v1.2.x/metrics.html b/docs/v1.2.x/metrics.html index 0777113d7e..5505062d39 100644 --- a/docs/v1.2.x/metrics.html +++ b/docs/v1.2.x/metrics.html @@ -1,22 +1,26 @@ - + - -Metrics | Eraser Docs + +Metrics | Eraser Docs - - - + + + -
-
Version: v1.2.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

Below is the list of metrics provided by Eraser per run:

Eraser

- count
- name: images_removed_run_total
- description: Total images removed by eraser

Scanner

- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected

ImageJob

- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
- - +
Version: v1.2.x

Metrics

To view Eraser metrics, you will need to deploy an Open Telemetry collector in the 'eraser-system' namespace, and an exporter. An example collector with a Prometheus exporter is otelcollector.yaml, and the endpoint can be specified using the configmap. In this example, we are logging the collected data to the otel-collector pod, and exporting metrics through Prometheus at 'http://localhost:8889/metrics', but a separate exporter can also be configured.

+

Below is the list of metrics provided by Eraser per run:

+

Eraser

+
- count
- name: images_removed_run_total
- description: Total images removed by eraser
+

Scanner

+
- count
- name: vulnerable_images_run_total
- description: Total vulnerable images detected
+

ImageJob

+
- count
- name: imagejob_run_total
- description: Total ImageJobs scheduled
- name: pods_completed_run_total
- description: Total pods completed
- name: pods_failed_run_total
- description: Total pods failed
- summary
- name: imagejob_duration_run_seconds
- description: Total time for ImageJobs scheduled to complete
\ No newline at end of file diff --git a/docs/v1.2.x/quick-start.html b/docs/v1.2.x/quick-start.html index 2c9688533f..72f4fe8f61 100644 --- a/docs/v1.2.x/quick-start.html +++ b/docs/v1.2.x/quick-start.html @@ -1,22 +1,43 @@ - + - -Quick Start | Eraser Docs + +Quick Start | Eraser Docs - - - + + + -
-
Version: v1.2.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

Deploy a DaemonSet

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

First, apply the DaemonSet:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s

Delete the DaemonSet:

$ kubectl delete daemonset alpine

Verify that the Pods have been deleted:

$ kubectl get pods
No resources found in default namespace.

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

List the nodes:

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0

List the images then filter for alpine:

$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

Automatically Cleaning Images

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
- - +
Version: v1.2.x

Quick Start

This tutorial demonstrates the functionality of Eraser and validates that non-running images are removed succesfully.

+

Deploy a DaemonSet

+

After following the install instructions, we'll apply a demo DaemonSet. For illustrative purposes, a DaemonSet is applied and deleted so the non-running images remain on all nodes. The alpine image with the 3.7.3 tag will be used in this example. This is an image with a known critical vulnerability.

+

First, apply the DaemonSet:

+
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
spec:
selector:
matchLabels:
app: alpine
template:
metadata:
labels:
app: alpine
spec:
containers:
- name: alpine
image: docker.io/library/alpine:3.7.3
EOF
+

Next, verify that the Pods are running or completed. After the alpine Pods complete, you may see a CrashLoopBackoff status. This is expected behavior from the alpine image and can be ignored for the tutorial.

+
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
alpine-2gh9c 1/1 Running 1 (3s ago) 6s
alpine-hljp9 0/1 Completed 1 (3s ago) 6s
+

Delete the DaemonSet:

+
$ kubectl delete daemonset alpine
+

Verify that the Pods have been deleted:

+
$ kubectl get pods
No resources found in default namespace.
+

To verify that the alpine images are still on the nodes, exec into one of the worker nodes and list the images. If you are not using a kind cluster or Docker for your container nodes, you will need to adjust the exec command accordingly.

+

List the nodes:

+
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45m v1.24.0
kind-worker Ready <none> 45m v1.24.0
kind-worker2 Ready <none> 44m v1.24.0
+

List the images then filter for alpine:

+
$ docker exec kind-worker ctr -n k8s.io images list | grep alpine
docker.io/library/alpine:3.7.3 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed
docker.io/library/alpine@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 application/vnd.docker.distribution.manifest.list.v2+json sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 2.0 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed

+

Automatically Cleaning Images

+

After deploying Eraser, it will automatically clean images in a regular interval. This interval can be set using the manager.scheduling.repeatInterval setting in the configmap. The default interval is 24 hours (24h). Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

+

Eraser will schedule eraser pods to each node in the cluster, and each pod will contain 3 containers: collector, scanner, and remover that will run to completion.

+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-sb789 0/3 Completed 0 26m
eraser-system eraser-kind-worker-j84hm 0/3 Completed 0 26m
eraser-system eraser-kind-worker2-4lbdr 0/3 Completed 0 26m
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 26m
+

The collector container sends the list of all images to the scanner container, which scans and reports non-compliant images to the remover container for removal of images that are non-running. Once all pods are completed, they will be automatically cleaned up.

+
+

If you want to remove all the images periodically, you can skip the scanner container by setting the components.scanner.enabled value to false using the configmap. In this case, each collector pod will hold 2 containers: collector and remover.

+
+
$ kubectl get pods -n eraser-system
NAMESPACE NAME READY STATUS RESTARTS AGE
eraser-system eraser-kind-control-plane-ksk2b 0/2 Completed 0 50s
eraser-system eraser-kind-worker-cpgqc 0/2 Completed 0 50s
eraser-system eraser-kind-worker2-k25df 0/2 Completed 0 50s
eraser-system eraser-controller-manager-86cdb4cbf9-x8d7q 1/1 Running 0 55s
\ No newline at end of file diff --git a/docs/v1.2.x/releasing.html b/docs/v1.2.x/releasing.html index 79d65dc96e..969b79c53c 100644 --- a/docs/v1.2.x/releasing.html +++ b/docs/v1.2.x/releasing.html @@ -1,23 +1,40 @@ - + - -Releasing | Eraser Docs + +Releasing | Eraser Docs - - - + + + -
-
Version: v1.2.x

Releasing

Create Release Pull Request

  1. Go to create_release_pull_request workflow under actions.
  2. Select run workflow, and use the workflow from your branch.
  3. Input release version with the semantic version identifying the release.
  4. Click run workflow and review the PR created by github-actions.

Releasing

  1. Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
  2. Pushing the release tag will trigger GitHub Actions to trigger release job. -This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

Publishing

  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
- - +
Version: v1.2.x

Releasing

Create Release Pull Request

+
    +
  1. Go to create_release_pull_request workflow under actions.
  2. +
  3. Select run workflow, and use the workflow from your branch.
  4. +
  5. Input release version with the semantic version identifying the release.
  6. +
  7. Click run workflow and review the PR created by github-actions.
  8. +
+

Releasing

+
    +
  1. +

    Once the PR is merged to main, tag that commit with release version and push tags to remote repository.

    +
    git checkout <BRANCH NAME>
    git pull origin <BRANCH NAME>
    git tag -a <NEW VERSION> -m '<NEW VERSION>'
    git push origin <NEW VERSION>
    +
  2. +
  3. +

    Pushing the release tag will trigger GitHub Actions to trigger release job. +This will build the ghcr.io/eraser-dev/remover, ghcr.io/eraser-dev/eraser-manager, ghcr.io/eraser-dev/collector, and ghcr.io/eraser-dev/eraser-trivy-scanner images automatically, then publish the new release tag.

    +
  4. +
+

Publishing

+
    +
  1. GitHub Action will create a new release, review and edit it at https://github.com/eraser-dev/eraser/releases
  2. +
\ No newline at end of file diff --git a/docs/v1.2.x/setup.html b/docs/v1.2.x/setup.html index a96a883f34..1b80f00d99 100644 --- a/docs/v1.2.x/setup.html +++ b/docs/v1.2.x/setup.html @@ -1,23 +1,161 @@ - + - -Setup | Eraser Docs + +Setup | Eraser Docs - - - + + + -
-
Version: v1.2.x

Development Setup

This document describes the steps to get started with development. -You can either utilize Codespaces or setup a local environment.

Local Setup

Prerequisites:

Get things running

  • Get dependencies with go get

  • This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

Making changes

Please refer to Development Reference for more details on the specific commands.

To test your changes on a cluster:

# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy

To test your changes to manager locally:

make run

Example Output:

you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...

Development Reference

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

Common Configuration

Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image

Linting

  • make lint

Lints the go code.

Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.

Development

  • make generate

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

  • make manifests

Generates the eraser deployment yaml files under manifest_staging/deploy.

Configuration Options:

Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
  • make test

Runs the unit tests for the eraser project.

Configuration Options:

Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
  • make e2e-test

Runs e2e tests on a cluster.

Configuration Options:

Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags

Build

  • make build

Builds the eraser manager binaries.

  • make run

Runs the eraser manager on your local machine.

  • make docker-build-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-manager

Builds the docker image for the eraser manager.

Configuration Options:

Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-remover

Builds the docker image for eraser remover.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-remover

Builds the docker image for the eraser remover.

Configuration Options:

Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-build-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
  • make docker-push-collector

Builds the docker image for the eraser collector.

Configuration Options:

Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.

Deployment

  • make install

Install CRDs into the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make uninstall

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
  • make deploy

Deploys eraser to the cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
  • make undeploy

Undeploy controller from the K8s cluster specified in ~/.kube/config.

Configuration Options:

Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.

Release

  • make release-manifest

Generates k8s manifests files for a release.

Configuration Options:

Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
  • make promote-staging-manifest

Promotes the k8s deployment yaml files to release.

- - +
Version: v1.2.x

Development Setup

+

This document describes the steps to get started with development. +You can either utilize Codespaces or setup a local environment.

+

Local Setup

+

Prerequisites:

+ +

Get things running

+
    +
  • +

    Get dependencies with go get

    +
  • +
  • +

    This project uses make. You can utilize make help to see available targets. For local deployment make targets help to build, test and deploy.

    +
  • +
+

Making changes

+

Please refer to Development Reference for more details on the specific commands.

+

To test your changes on a cluster:

+
# generate necessary api files (optional - only needed if changes to api folder).
make generate

# build applicable images
make docker-build-manager MANAGER_IMG=eraser-manager:dev
make docker-build-remover REMOVER_IMG=remover:dev
make docker-build-collector COLLECTOR_IMG=collector:dev
make docker-build-trivy-scanner TRIVY_SCANNER_IMG=eraser-trivy-scanner:dev

# make sure updated image is present on cluster (e.g., see kind example below)
kind load docker-image \
eraser-manager:dev \
eraser-trivy-scanner:dev \
remover:dev \
collector:dev

make manifests
make deploy

# to remove the deployment
make undeploy
+

To test your changes to manager locally:

+
make run
+

Example Output:

+
you@local:~/eraser$ make run
docker build . \
-t eraser-tooling \
-f build/tooling/Dockerfile
[+] Building 7.8s (8/8) FINISHED
=> => naming to docker.io/library/eraser-tooling 0.0s
docker run -v /home/eraser/config:/config -w /config/manager \
registry.k8s.io/kustomize/kustomize:v3.8.9 edit set image controller=eraser-manager:dev
docker run -v /home/eraser:/eraser eraser-tooling controller-gen \
crd \
rbac:roleName=manager-role \
webhook \
paths="./..." \
output:crd:artifacts:config=config/crd/bases
rm -rf manifest_staging
mkdir -p manifest_staging/deploy
docker run --rm -v /home/eraser:/eraser \
registry.k8s.io/kustomize/kustomize:v3.8.9 build \
/eraser/config/default -o /eraser/manifest_staging/deploy/eraser.yaml
docker run -v /home/eraser:/eraser eraser-tooling controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./main.go
{"level":"info","ts":1652985685.1663408,"logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
...
+

Development Reference

+

Eraser is using tooling from kubebuilder. For Eraser this tooling is containerized into the eraser-tooling image. The make targets can use this tooling and build the image when necessary.

+

You can override the default configuration using environment variables. Below you can find a reference of targets and configuration options.

+

Common Configuration

+
Environment VariableDescription
VERSIONSpecifies the version (i.e., the image tag) of eraser to be used.
MANAGER_IMGDefines the image url for the Eraser manager. Used for tagging, pulling and pushing the image
REMOVER_IMGDefines the image url for the Eraser. Used for tagging, pulling and pushing the image
COLLECTOR_IMGDefines the image url for the Collector. Used for tagging, pulling and pushing the image
+

Linting

+
    +
  • make lint
  • +
+

Lints the go code.

+
Environment VariableDescription
GOLANGCI_LINTSpecifies the go linting binary to be used for linting.
+

Development

+
    +
  • make generate
  • +
+

Generates necessary files for the k8s api stored under api/v1alpha1/zz_generated.deepcopy.go. See the kubebuilder docs for details.

+
    +
  • make manifests
  • +
+

Generates the eraser deployment yaml files under manifest_staging/deploy.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGDefines the image url for the Eraser.
MANAGER_IMGDefines the image url for the Eraser manager.
KUSTOMIZE_VERSIONDefine Kustomize version for generating manifests.
+
    +
  • make test
  • +
+

Runs the unit tests for the eraser project.

+

Configuration Options:

+
Environment VariableDescription
ENVTESTSpecifies the envtest setup binary.
ENVTEST_K8S_VERSIONSpecifies the Kubernetes version for envtest setup command.
+
    +
  • make e2e-test
  • +
+

Runs e2e tests on a cluster.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGEraser image to be used for e2e test.
MANAGER_IMGEraser manager image to be used for e2e test.
KUBERNETES_VERSIONKubernetes version for e2e test.
TEST_COUNTSets repetition for test. Please refer to go docs for details.
TIMEOUTSets timeout for test. Please refer to go docs for details.
TESTFLAGSSets additional test flags
+

Build

+
    +
  • make build
  • +
+

Builds the eraser manager binaries.

+
    +
  • make run
  • +
+

Runs the eraser manager on your local machine.

+
    +
  • make docker-build-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-manager
  • +
+

Builds the docker image for the eraser manager.

+

Configuration Options:

+
Environment VariableDescription
MANAGER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-remover
  • +
+

Builds the docker image for eraser remover.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-remover
  • +
+

Builds the docker image for the eraser remover.

+

Configuration Options:

+
Environment VariableDescription
REMOVER_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-build-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
CACHE_FROMSets the target of the buildx --cache-from flag see buildx reference.
CACHE_TOSets the target of the buildx --cache-to flag see buildx reference.
PLATFORMSets the target platform for buildx see buildx reference.
OUTPUT_TYPESets the output for buildx see buildx reference.
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+
    +
  • make docker-push-collector
  • +
+

Builds the docker image for the eraser collector.

+

Configuration Options:

+
Environment VariableDescription
COLLECTOR_IMGSpecifies the target repository, image name and tag for building image.
+

Deployment

+
    +
  • make install
  • +
+

Install CRDs into the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make uninstall
  • +
+

Uninstall CRDs from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
+
    +
  • make deploy
  • +
+

Deploys eraser to the cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources for deployment.
MANAGER_IMGSpecifies the eraser manager image version to be used for deployment
+
    +
  • make undeploy
  • +
+

Undeploy controller from the K8s cluster specified in ~/.kube/config.

+

Configuration Options:

+
Environment VariableDescription
KUSTOMIZE_VERSIONKustomize version used to generate k8s resources that need to be removed.
+

Release

+
    +
  • make release-manifest
  • +
+

Generates k8s manifests files for a release.

+

Configuration Options:

+
Environment VariableDescription
NEWVERSIONSets the new version in the Makefile
+
    +
  • make promote-staging-manifest
  • +
+

Promotes the k8s deployment yaml files to release.

\ No newline at end of file diff --git a/docs/v1.2.x/trivy.html b/docs/v1.2.x/trivy.html index 69236bc03b..6349f19e37 100644 --- a/docs/v1.2.x/trivy.html +++ b/docs/v1.2.x/trivy.html @@ -1,22 +1,20 @@ - + - -Trivy | Eraser Docs + +Trivy | Eraser Docs - - - + + + -
-
Version: v1.2.x

Trivy

Trivy Provider Options

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

- - +
Version: v1.2.x

Trivy

Trivy Provider Options

+

The trivy provider is used in Eraser for image scanning and detecting vulnerabilities. See Customization for more details on configuring the scanner.

\ No newline at end of file