Compare commits
1 Commits
feat/slack
...
runtime-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f7c4924c1 |
@@ -1,5 +0,0 @@
|
|||||||
[target.x86_64-pc-windows-msvc]
|
|
||||||
rustflags = ["-C", "link-arg=/STACK:8000000"]
|
|
||||||
|
|
||||||
[target.x86_64-pc-windows-gnu]
|
|
||||||
rustflags = ["-C", "link-arg=-Wl,--stack,8000000"]
|
|
||||||
404
Cargo.lock
generated
404
Cargo.lock
generated
@@ -4,13 +4,19 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.24.2"
|
version = "0.21.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gimli",
|
"gimli",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler2"
|
name = "adler2"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -54,15 +60,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.12"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"const-random",
|
"const-random",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
"zerocopy",
|
"zerocopy 0.7.35",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -192,17 +198,17 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.75"
|
version = "0.3.71"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"addr2line",
|
"addr2line",
|
||||||
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.7.4",
|
||||||
"object",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -248,9 +254,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.1"
|
version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -350,9 +356,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.22"
|
version = "1.2.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1"
|
checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
@@ -407,9 +413,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.38"
|
version = "4.5.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
|
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@@ -417,9 +423,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.38"
|
version = "4.5.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
|
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@@ -447,9 +453,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color-eyre"
|
name = "color-eyre"
|
||||||
version = "0.6.4"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e1761c0e16f8883bbbb8ce5990867f4f06bf11a0253da6495a04ce4b6ef0ec"
|
checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"color-spantrace",
|
"color-spantrace",
|
||||||
@@ -462,9 +468,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color-spantrace"
|
name = "color-spantrace"
|
||||||
version = "0.2.2"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ddd8d5bfda1e11a501d0a7303f3bfed9aa632ebdb859be40d0fd70478ed70d5"
|
checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"owo-colors",
|
"owo-colors",
|
||||||
@@ -518,15 +524,6 @@ dependencies = [
|
|||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "convert_case"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-segmentation",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@@ -608,7 +605,7 @@ version = "0.28.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"mio 1.0.3",
|
"mio 1.0.3",
|
||||||
@@ -930,15 +927,6 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "email_address"
|
|
||||||
version = "0.2.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.35"
|
version = "0.8.35"
|
||||||
@@ -1032,8 +1020,8 @@ dependencies = [
|
|||||||
"cidr",
|
"cidr",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"harmony",
|
"harmony",
|
||||||
"harmony_cli",
|
|
||||||
"harmony_macros",
|
"harmony_macros",
|
||||||
|
"harmony_tui",
|
||||||
"harmony_types",
|
"harmony_types",
|
||||||
"log",
|
"log",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1124,7 +1112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide 0.8.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1175,16 +1163,6 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fqdn"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c0f5d7f7b3eed2f771fc7f6fcb651f9560d7b0c483d75876082acb4649d266b3"
|
|
||||||
dependencies = [
|
|
||||||
"punycode",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -1324,9 +1302,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.3"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1346,9 +1324,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.28.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "group"
|
name = "group"
|
||||||
@@ -1382,9 +1360,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.10"
|
version = "0.4.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5"
|
checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1405,13 +1383,10 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"cidr",
|
"cidr",
|
||||||
"convert_case",
|
|
||||||
"derive-new",
|
"derive-new",
|
||||||
"directories",
|
"directories",
|
||||||
"dockerfile_builder",
|
"dockerfile_builder",
|
||||||
"email_address",
|
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"fqdn",
|
|
||||||
"harmony_macros",
|
"harmony_macros",
|
||||||
"harmony_types",
|
"harmony_types",
|
||||||
"helm-wrapper-rs",
|
"helm-wrapper-rs",
|
||||||
@@ -1434,7 +1409,6 @@ dependencies = [
|
|||||||
"serde-value",
|
"serde-value",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"temp-dir",
|
|
||||||
"temp-file",
|
"temp-file",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
@@ -1492,9 +1466,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.3"
|
version = "0.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
|
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"equivalent",
|
"equivalent",
|
||||||
@@ -1708,7 +1682,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.4.10",
|
"h2 0.4.9",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -1847,22 +1821,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "2.0.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
|
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"potential_utf",
|
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_locale_core"
|
name = "icu_locid"
|
||||||
version = "2.0.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
|
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"litemap",
|
"litemap",
|
||||||
@@ -1872,10 +1845,30 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_normalizer"
|
name = "icu_locid_transform"
|
||||||
version = "2.0.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
|
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"icu_locid",
|
||||||
|
"icu_locid_transform_data",
|
||||||
|
"icu_provider",
|
||||||
|
"tinystr",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locid_transform_data"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_normalizer"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"icu_collections",
|
"icu_collections",
|
||||||
@@ -1883,54 +1876,67 @@ dependencies = [
|
|||||||
"icu_properties",
|
"icu_properties",
|
||||||
"icu_provider",
|
"icu_provider",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
"utf16_iter",
|
||||||
|
"utf8_iter",
|
||||||
|
"write16",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_normalizer_data"
|
name = "icu_normalizer_data"
|
||||||
version = "2.0.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
|
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_properties"
|
name = "icu_properties"
|
||||||
version = "2.0.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a"
|
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"icu_collections",
|
"icu_collections",
|
||||||
"icu_locale_core",
|
"icu_locid_transform",
|
||||||
"icu_properties_data",
|
"icu_properties_data",
|
||||||
"icu_provider",
|
"icu_provider",
|
||||||
"potential_utf",
|
"tinystr",
|
||||||
"zerotrie",
|
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_properties_data"
|
name = "icu_properties_data"
|
||||||
version = "2.0.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04"
|
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_provider"
|
name = "icu_provider"
|
||||||
version = "2.0.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
|
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"icu_locale_core",
|
"icu_locid",
|
||||||
|
"icu_provider_macros",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
"tinystr",
|
"tinystr",
|
||||||
"writeable",
|
"writeable",
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
"zerotrie",
|
|
||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_provider_macros"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -1950,9 +1956,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna_adapter"
|
name = "idna_adapter"
|
||||||
version = "1.2.1"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
|
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"icu_normalizer",
|
"icu_normalizer",
|
||||||
"icu_properties",
|
"icu_properties",
|
||||||
@@ -1996,7 +2002,7 @@ version = "0.7.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
|
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"crossterm 0.25.0",
|
"crossterm 0.25.0",
|
||||||
"dyn-clone",
|
"dyn-clone",
|
||||||
"fuzzy-matcher",
|
"fuzzy-matcher",
|
||||||
@@ -2059,9 +2065,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jiff"
|
name = "jiff"
|
||||||
version = "0.2.13"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806"
|
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jiff-static",
|
"jiff-static",
|
||||||
"log",
|
"log",
|
||||||
@@ -2072,9 +2078,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jiff-static"
|
name = "jiff-static"
|
||||||
version = "0.2.13"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48"
|
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2233,9 +2239,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
version = "0.2.15"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredfish"
|
name = "libredfish"
|
||||||
@@ -2256,7 +2262,7 @@ version = "0.1.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2274,9 +2280,9 @@ checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.8.0"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -2330,6 +2336,15 @@ version = "0.3.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.8"
|
version = "0.8.8"
|
||||||
@@ -2474,18 +2489,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.36.7"
|
version = "0.32.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "octocrab"
|
name = "octocrab"
|
||||||
version = "0.44.1"
|
version = "0.44.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86996964f8b721067b6ed238aa0ccee56ecad6ee5e714468aa567992d05d2b91"
|
checksum = "aaf799a9982a4d0b4b3fa15b4c1ff7daf5bd0597f46456744dcbb6ddc2e4c827"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -2539,7 +2554,7 @@ version = "0.10.72"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2567,9 +2582,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.108"
|
version = "0.9.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
|
checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2633,9 +2648,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owo-colors"
|
name = "owo-colors"
|
||||||
version = "4.2.0"
|
version = "3.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "p256"
|
name = "p256"
|
||||||
@@ -2921,15 +2936,6 @@ dependencies = [
|
|||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "potential_utf"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
|
|
||||||
dependencies = [
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -2942,7 +2948,7 @@ version = "0.2.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy",
|
"zerocopy 0.8.25",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3000,12 +3006,6 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "punycode"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
@@ -3083,7 +3083,7 @@ version = "0.9.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3092,7 +3092,7 @@ version = "0.29.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
"compact_str",
|
"compact_str",
|
||||||
"crossterm 0.28.1",
|
"crossterm 0.28.1",
|
||||||
@@ -3109,11 +3109,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.12"
|
version = "0.5.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
|
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3207,7 +3207,7 @@ dependencies = [
|
|||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2 0.4.10",
|
"h2 0.4.9",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
@@ -3296,7 +3296,7 @@ dependencies = [
|
|||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cbc",
|
"cbc",
|
||||||
"chacha20",
|
"chacha20",
|
||||||
@@ -3397,7 +3397,7 @@ version = "2.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3bb94393cafad0530145b8f626d8687f1ee1dedb93d7ba7740d6ae81868b13b5"
|
checksum = "3bb94393cafad0530145b8f626d8687f1ee1dedb93d7ba7740d6ae81868b13b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"flurry",
|
"flurry",
|
||||||
@@ -3444,7 +3444,7 @@ version = "0.38.44"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.4.15",
|
"linux-raw-sys 0.4.15",
|
||||||
@@ -3453,11 +3453,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "1.0.7"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.9.4",
|
"linux-raw-sys 0.9.4",
|
||||||
@@ -3466,9 +3466,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.27"
|
version = "0.23.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
|
checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -3524,18 +3524,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.12.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
|
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
||||||
dependencies = [
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
version = "0.103.3"
|
version = "0.103.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435"
|
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ring",
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@@ -3618,7 +3615,7 @@ version = "2.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -3631,7 +3628,7 @@ version = "3.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
|
checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"core-foundation 0.10.0",
|
"core-foundation 0.10.0",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -3762,9 +3759,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.9"
|
version = "0.10.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
@@ -3788,9 +3785,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.18"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
@@ -4026,9 +4023,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "synstructure"
|
||||||
version = "0.13.2"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -4052,7 +4049,7 @@ version = "0.6.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"system-configuration-sys 0.6.0",
|
"system-configuration-sys 0.6.0",
|
||||||
]
|
]
|
||||||
@@ -4083,12 +4080,6 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "temp-dir"
|
|
||||||
version = "0.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "83176759e9416cf81ee66cb6508dbfe9c96f20b8b56265a39917551c23c70964"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "temp-file"
|
name = "temp-file"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@@ -4097,14 +4088,14 @@ checksum = "b5ff282c3f91797f0acb021f3af7fffa8a78601f0f2fd0a9f79ee7dcf9a9af9e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.20.0"
|
version = "3.19.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
|
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.0.7",
|
"rustix 1.0.5",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4206,9 +4197,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.8.1"
|
version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
|
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"zerovec",
|
"zerovec",
|
||||||
@@ -4216,9 +4207,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.45.0"
|
version = "1.44.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
|
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -4305,12 +4296,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-http"
|
name = "tower-http"
|
||||||
version = "0.6.4"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e"
|
checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
@@ -4492,6 +4483,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf16_iter"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8_iter"
|
name = "utf8_iter"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -4510,7 +4507,7 @@ version = "1.16.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.2",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
"uuid-macro-internal",
|
"uuid-macro-internal",
|
||||||
]
|
]
|
||||||
@@ -5011,14 +5008,20 @@ version = "0.39.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "write16"
|
||||||
version = "0.6.1"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
|
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "writeable"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wyz"
|
name = "wyz"
|
||||||
@@ -5067,9 +5070,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yoke"
|
name = "yoke"
|
||||||
version = "0.8.0"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
|
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
@@ -5079,9 +5082,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yoke-derive"
|
name = "yoke-derive"
|
||||||
version = "0.8.0"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
|
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -5089,13 +5092,33 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive 0.7.35",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.25"
|
version = "0.8.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
|
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive 0.8.25",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5136,22 +5159,11 @@ version = "1.8.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerotrie"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerovec"
|
name = "zerovec"
|
||||||
version = "0.11.2"
|
version = "0.10.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
|
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
@@ -5160,9 +5172,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerovec-derive"
|
name = "zerovec-derive"
|
||||||
version = "0.11.1"
|
version = "0.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
|
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ serde_yaml = "0.9.34"
|
|||||||
serde-value = "0.7.0"
|
serde-value = "0.7.0"
|
||||||
http = "1.2.0"
|
http = "1.2.0"
|
||||||
inquire = "0.7.5"
|
inquire = "0.7.5"
|
||||||
convert_case = "0.8.0"
|
|
||||||
|
|
||||||
[workspace.dependencies.uuid]
|
[workspace.dependencies.uuid]
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|||||||
138
README.md
138
README.md
@@ -31,141 +31,3 @@ Options:
|
|||||||
|
|
||||||

|

|
||||||
````
|
````
|
||||||
## Supporting a new field in OPNSense `config.xml`
|
|
||||||
|
|
||||||
Two steps:
|
|
||||||
- Supporting the field in `opnsense-config-xml`
|
|
||||||
- Enabling Harmony to control the field
|
|
||||||
|
|
||||||
We'll use the `filename` field in the `dhcpcd` section of the file as an example.
|
|
||||||
|
|
||||||
### Supporting the field
|
|
||||||
|
|
||||||
As type checking if enforced, every field from `config.xml` must be known by the code. Each subsection of `config.xml` has its `.rs` file. For the `dhcpcd` section, we'll modify `opnsense-config-xml/src/data/dhcpd.rs`.
|
|
||||||
|
|
||||||
When a new field appears in the xml file, an error like this will be thrown and Harmony will panic :
|
|
||||||
```
|
|
||||||
Running `/home/stremblay/nt/dir/harmony/target/debug/example-nanodc`
|
|
||||||
Found unauthorized element filename
|
|
||||||
thread 'main' panicked at opnsense-config-xml/src/data/opnsense.rs:54:14:
|
|
||||||
OPNSense received invalid string, should be full XML: ()
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Define the missing field (`filename`) in the `DhcpInterface` struct of `opnsense-config-xml/src/data/dhcpd.rs`:
|
|
||||||
```
|
|
||||||
pub struct DhcpInterface {
|
|
||||||
...
|
|
||||||
pub filename: Option<String>,
|
|
||||||
```
|
|
||||||
|
|
||||||
Harmony should now be fixed, build and run.
|
|
||||||
|
|
||||||
### Controlling the field
|
|
||||||
|
|
||||||
Define the `xml field setter` in `opnsense-config/src/modules/dhcpd.rs`.
|
|
||||||
```
|
|
||||||
impl<'a> DhcpConfig<'a> {
|
|
||||||
...
|
|
||||||
pub fn set_filename(&mut self, filename: &str) {
|
|
||||||
self.enable_netboot();
|
|
||||||
self.get_lan_dhcpd().filename = Some(filename.to_string());
|
|
||||||
}
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Define the `value setter` in the `DhcpServer trait` in `domain/topology/network.rs`
|
|
||||||
```
|
|
||||||
#[async_trait]
|
|
||||||
pub trait DhcpServer: Send + Sync {
|
|
||||||
...
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError>;
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Implement the `value setter` in each `DhcpServer` implementation.
|
|
||||||
`infra/opnsense/dhcp.rs`:
|
|
||||||
```
|
|
||||||
#[async_trait]
|
|
||||||
impl DhcpServer for OPNSenseFirewall {
|
|
||||||
...
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filename(filename);
|
|
||||||
debug!("OPNsense dhcp server set filename {filename}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
`domain/topology/ha_cluster.rs`
|
|
||||||
```
|
|
||||||
#[async_trait]
|
|
||||||
impl DhcpServer for DummyInfra {
|
|
||||||
...
|
|
||||||
async fn set_filename(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Add the new field to the DhcpScore in `modules/dhcp.rs`
|
|
||||||
```
|
|
||||||
pub struct DhcpScore {
|
|
||||||
...
|
|
||||||
pub filename: Option<String>,
|
|
||||||
```
|
|
||||||
|
|
||||||
Define it in its implementation in `modules/okd/dhcp.rs`
|
|
||||||
```
|
|
||||||
impl OKDDhcpScore {
|
|
||||||
...
|
|
||||||
Self {
|
|
||||||
dhcp_score: DhcpScore {
|
|
||||||
...
|
|
||||||
filename: Some("undionly.kpxe".to_string()),
|
|
||||||
```
|
|
||||||
|
|
||||||
Define it in its implementation in `modules/okd/bootstrap_dhcp.rs`
|
|
||||||
```
|
|
||||||
impl OKDDhcpScore {
|
|
||||||
...
|
|
||||||
Self {
|
|
||||||
dhcp_score: DhcpScore::new(
|
|
||||||
...
|
|
||||||
Some("undionly.kpxe".to_string()),
|
|
||||||
```
|
|
||||||
|
|
||||||
Update the interpret (function called by the `execute` fn of the interpret) so it now updates the `filename` field value in `modules/dhcp.rs`
|
|
||||||
```
|
|
||||||
impl DhcpInterpret {
|
|
||||||
...
|
|
||||||
let filename_outcome = match &self.score.filename {
|
|
||||||
Some(filename) => {
|
|
||||||
let dhcp_server = Arc::new(topology.dhcp_server.clone());
|
|
||||||
dhcp_server.set_filename(&filename).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filename to {filename}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if next_server_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& boot_filename_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& filename_outcome.status == InterpretStatus::NOOP
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
Ok(Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!(
|
|
||||||
"Dhcp Interpret Set next boot to [{:?}], boot_filename to [{:?}], filename to [{:?}]",
|
|
||||||
self.score.boot_filename, self.score.boot_filename, self.score.filename
|
|
||||||
)
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
slitaz/* filter=lfs diff=lfs merge=lfs -text
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set hostfile ${base-url}/byMAC/01-${mac:hexhyp}.ipxe
|
|
||||||
|
|
||||||
chain ${hostfile} || chain ${base-url}/default.ipxe
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item okdinstallation Install OKD
|
|
||||||
item slitaz Boot to Slitaz - old linux for debugging
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# okdinstallation
|
|
||||||
#################################
|
|
||||||
:okdinstallation
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set kernel-image fcos/fedora-coreos-39.20231101.3.0-live-kernel-x86_64
|
|
||||||
set live-rootfs fcos/fedora-coreos-39.20231101.3.0-live-rootfs.x86_64.img
|
|
||||||
set live-initramfs fcos/fedora-coreos-39.20231101.3.0-live-initramfs.x86_64.img
|
|
||||||
set install-disk /dev/nvme0n1
|
|
||||||
set ignition-file ncd0/master.ign
|
|
||||||
|
|
||||||
kernel ${base-url}/${kernel-image} initrd=main coreos.live.rootfs_url=${base-url}/${live-rootfs} coreos.inst.install_dev=${install-disk} coreos.inst.ignition_url=${base-url}/${ignition-file} ip=enp1s0:dhcp
|
|
||||||
initrd --name main ${base-url}/${live-initramfs}
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item okdinstallation Install OKD
|
|
||||||
item slitaz Boot to Slitaz - old linux for debugging
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# okdinstallation
|
|
||||||
#################################
|
|
||||||
:okdinstallation
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set kernel-image fcos/fedora-coreos-39.20231101.3.0-live-kernel-x86_64
|
|
||||||
set live-rootfs fcos/fedora-coreos-39.20231101.3.0-live-rootfs.x86_64.img
|
|
||||||
set live-initramfs fcos/fedora-coreos-39.20231101.3.0-live-initramfs.x86_64.img
|
|
||||||
set install-disk /dev/nvme0n1
|
|
||||||
set ignition-file ncd0/master.ign
|
|
||||||
|
|
||||||
kernel ${base-url}/${kernel-image} initrd=main coreos.live.rootfs_url=${base-url}/${live-rootfs} coreos.inst.install_dev=${install-disk} coreos.inst.ignition_url=${base-url}/${ignition-file} ip=enp1s0:dhcp
|
|
||||||
initrd --name main ${base-url}/${live-initramfs}
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item okdinstallation Install OKD
|
|
||||||
item slitaz Slitaz - an old linux image for debugging
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# okdinstallation
|
|
||||||
#################################
|
|
||||||
:okdinstallation
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set kernel-image fcos/fedora-coreos-39.20231101.3.0-live-kernel-x86_64
|
|
||||||
set live-rootfs fcos/fedora-coreos-39.20231101.3.0-live-rootfs.x86_64.img
|
|
||||||
set live-initramfs fcos/fedora-coreos-39.20231101.3.0-live-initramfs.x86_64.img
|
|
||||||
set install-disk /dev/sda
|
|
||||||
set ignition-file ncd0/worker.ign
|
|
||||||
|
|
||||||
kernel ${base-url}/${kernel-image} initrd=main coreos.live.rootfs_url=${base-url}/${live-rootfs} coreos.inst.install_dev=${install-disk} coreos.inst.ignition_url=${base-url}/${ignition-file} ip=enp1s0:dhcp
|
|
||||||
initrd --name main ${base-url}/${live-initramfs}
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item okdinstallation Install OKD
|
|
||||||
item slitaz Boot to Slitaz - old linux for debugging
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# okdinstallation
|
|
||||||
#################################
|
|
||||||
:okdinstallation
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set kernel-image fcos/fedora-coreos-39.20231101.3.0-live-kernel-x86_64
|
|
||||||
set live-rootfs fcos/fedora-coreos-39.20231101.3.0-live-rootfs.x86_64.img
|
|
||||||
set live-initramfs fcos/fedora-coreos-39.20231101.3.0-live-initramfs.x86_64.img
|
|
||||||
set install-disk /dev/nvme0n1
|
|
||||||
set ignition-file ncd0/master.ign
|
|
||||||
|
|
||||||
kernel ${base-url}/${kernel-image} initrd=main coreos.live.rootfs_url=${base-url}/${live-rootfs} coreos.inst.install_dev=${install-disk} coreos.inst.ignition_url=${base-url}/${ignition-file} ip=enp1s0:dhcp
|
|
||||||
initrd --name main ${base-url}/${live-initramfs}
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item okdinstallation Install OKD
|
|
||||||
item slitaz Slitaz - an old linux image for debugging
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# okdinstallation
|
|
||||||
#################################
|
|
||||||
:okdinstallation
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set kernel-image fcos/fedora-coreos-39.20231101.3.0-live-kernel-x86_64
|
|
||||||
set live-rootfs fcos/fedora-coreos-39.20231101.3.0-live-rootfs.x86_64.img
|
|
||||||
set live-initramfs fcos/fedora-coreos-39.20231101.3.0-live-initramfs.x86_64.img
|
|
||||||
set install-disk /dev/sda
|
|
||||||
set ignition-file ncd0/worker.ign
|
|
||||||
|
|
||||||
kernel ${base-url}/${kernel-image} initrd=main coreos.live.rootfs_url=${base-url}/${live-rootfs} coreos.inst.install_dev=${install-disk} coreos.inst.ignition_url=${base-url}/${ignition-file} ip=enp1s0:dhcp
|
|
||||||
initrd --name main ${base-url}/${live-initramfs}
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item okdinstallation Install OKD
|
|
||||||
item slitaz Slitaz - an old linux image for debugging
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
# This is the bootstrap node
|
|
||||||
# it will become wk2
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# okdinstallation
|
|
||||||
#################################
|
|
||||||
:okdinstallation
|
|
||||||
set base-url http://192.168.33.1:8080
|
|
||||||
set kernel-image fcos/fedora-coreos-39.20231101.3.0-live-kernel-x86_64
|
|
||||||
set live-rootfs fcos/fedora-coreos-39.20231101.3.0-live-rootfs.x86_64.img
|
|
||||||
set live-initramfs fcos/fedora-coreos-39.20231101.3.0-live-initramfs.x86_64.img
|
|
||||||
set install-disk /dev/sda
|
|
||||||
set ignition-file ncd0/worker.ign
|
|
||||||
|
|
||||||
kernel ${base-url}/${kernel-image} initrd=main coreos.live.rootfs_url=${base-url}/${live-rootfs} coreos.inst.install_dev=${install-disk} coreos.inst.ignition_url=${base-url}/${ignition-file} ip=enp1s0:dhcp
|
|
||||||
initrd --name main ${base-url}/${live-initramfs}
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
menu PXE Boot Menu - [${mac}]
|
|
||||||
item local Boot from Hard Disk
|
|
||||||
item slitaz Boot slitaz live environment [tux|root:root]
|
|
||||||
#item ubuntu-server Ubuntu 24.04.1 live server
|
|
||||||
#item ubuntu-desktop Ubuntu 24.04.1 desktop
|
|
||||||
#item systemrescue System Rescue 11.03
|
|
||||||
item memtest memtest
|
|
||||||
#choose --default local --timeout 5000 selected
|
|
||||||
choose selected
|
|
||||||
|
|
||||||
goto ${selected}
|
|
||||||
|
|
||||||
:local
|
|
||||||
exit
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# slitaz
|
|
||||||
#################################
|
|
||||||
:slitaz
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/slitaz
|
|
||||||
kernel ${base_url}/vmlinuz-2.6.37-slitaz rw root=/dev/null vga=788 initrd=rootfs.gz
|
|
||||||
initrd ${base_url}/rootfs.gz
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# Ubuntu Server
|
|
||||||
#################################
|
|
||||||
:ubuntu-server
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/ubuntu/live-server-24.04.1
|
|
||||||
|
|
||||||
kernel ${base_url}/vmlinuz ip=dhcp url=${base_url}/ubuntu-24.04.1-live-server-amd64.iso autoinstall ds=nocloud
|
|
||||||
initrd ${base_url}/initrd
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# Ubuntu Desktop
|
|
||||||
#################################
|
|
||||||
:ubuntu-desktop
|
|
||||||
set server_ip 192.168.33.1:8080
|
|
||||||
set base_url http://${server_ip}/ubuntu/desktop-24.04.1
|
|
||||||
|
|
||||||
kernel ${base_url}/vmlinuz ip=dhcp url=${base_url}/ubuntu-24.04.1-desktop-amd64.iso autoinstall ds=nocloud
|
|
||||||
initrd ${base_url}/initrd
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# System Rescue
|
|
||||||
#################################
|
|
||||||
:systemrescue
|
|
||||||
set base-url http://192.168.33.1:8080/systemrescue
|
|
||||||
|
|
||||||
kernel ${base-url}/vmlinuz initrd=sysresccd.img boot=systemrescue docache
|
|
||||||
initrd ${base-url}/sysresccd.img
|
|
||||||
boot
|
|
||||||
|
|
||||||
#################################
|
|
||||||
# MemTest86 (BIOS/UEFI)
|
|
||||||
#################################
|
|
||||||
:memtest
|
|
||||||
iseq ${platform} efi && goto memtest_efi || goto memtest_bios
|
|
||||||
|
|
||||||
:memtest_efi
|
|
||||||
kernel http://192.168.33.1:8080/memtest/memtest64.efi
|
|
||||||
boot
|
|
||||||
|
|
||||||
:memtest_bios
|
|
||||||
kernel http://192.168.33.1:8080/memtest/memtest64.bin
|
|
||||||
boot
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
1
data/watchguard/pxe-http-files/paul
Normal file
1
data/watchguard/pxe-http-files/paul
Normal file
@@ -0,0 +1 @@
|
|||||||
|
hey i am paul
|
||||||
BIN
data/watchguard/pxe-http-files/slitaz/rootfs.gz
(Stored with Git LFS)
BIN
data/watchguard/pxe-http-files/slitaz/rootfs.gz
(Stored with Git LFS)
Binary file not shown.
BIN
data/watchguard/pxe-http-files/slitaz/vmlinuz-2.6.37-slitaz
(Stored with Git LFS)
BIN
data/watchguard/pxe-http-files/slitaz/vmlinuz-2.6.37-slitaz
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,7 +8,7 @@ publish = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
harmony = { path = "../../harmony" }
|
harmony = { path = "../../harmony" }
|
||||||
harmony_cli = { path = "../../harmony_cli" }
|
harmony_tui = { path = "../../harmony_tui" }
|
||||||
harmony_types = { path = "../../harmony_types" }
|
harmony_types = { path = "../../harmony_types" }
|
||||||
cidr = { workspace = true }
|
cidr = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
|||||||
@@ -1,85 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
print_r("Hello this is from PHP")
|
||||||
ini_set('display_errors', 1);
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
|
|
||||||
$host = getenv('MYSQL_HOST') ?: '';
|
|
||||||
$user = getenv('MYSQL_USER') ?: 'root';
|
|
||||||
$pass = getenv('MYSQL_PASSWORD') ?: '';
|
|
||||||
$db = 'testfill';
|
|
||||||
$charset = 'utf8mb4';
|
|
||||||
|
|
||||||
$dsn = "mysql:host=$host;charset=$charset";
|
|
||||||
$options = [
|
|
||||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
||||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$pdo = new PDO($dsn, $user, $pass, $options);
|
|
||||||
$pdo->exec("CREATE DATABASE IF NOT EXISTS `$db`");
|
|
||||||
$pdo->exec("USE `$db`");
|
|
||||||
$pdo->exec("
|
|
||||||
CREATE TABLE IF NOT EXISTS filler (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
data LONGBLOB
|
|
||||||
)
|
|
||||||
");
|
|
||||||
} catch (\PDOException $e) {
|
|
||||||
die("❌ DB connection failed: " . $e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDbStats($pdo, $db) {
|
|
||||||
$stmt = $pdo->query("
|
|
||||||
SELECT
|
|
||||||
ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_size_gb,
|
|
||||||
SUM(table_rows) AS total_rows
|
|
||||||
FROM information_schema.tables
|
|
||||||
WHERE table_schema = '$db'
|
|
||||||
");
|
|
||||||
$result = $stmt->fetch();
|
|
||||||
$sizeGb = $result['total_size_gb'] ?? '0';
|
|
||||||
$rows = $result['total_rows'] ?? '0';
|
|
||||||
$avgMb = ($rows > 0) ? round(($sizeGb * 1024) / $rows, 2) : 0;
|
|
||||||
return [$sizeGb, $rows, $avgMb];
|
|
||||||
}
|
|
||||||
|
|
||||||
list($dbSize, $rowCount, $avgRowMb) = getDbStats($pdo, $db);
|
|
||||||
|
|
||||||
$message = '';
|
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['fill'])) {
|
|
||||||
$iterations = 1024;
|
|
||||||
$data = str_repeat(random_bytes(1024), 1024); // 1MB
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO filler (data) VALUES (:data)");
|
|
||||||
|
|
||||||
for ($i = 0; $i < $iterations; $i++) {
|
|
||||||
$stmt->execute([':data' => $data]);
|
|
||||||
}
|
|
||||||
|
|
||||||
list($dbSize, $rowCount, $avgRowMb) = getDbStats($pdo, $db);
|
|
||||||
|
|
||||||
$message = "<p style='color: green;'>✅ 1GB inserted into MariaDB successfully.</p>";
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>MariaDB Filler</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>MariaDB Storage Filler</h1>
|
|
||||||
<?= $message ?>
|
|
||||||
<ul>
|
|
||||||
<li><strong>📦 MariaDB Used Size:</strong> <?= $dbSize ?> GB</li>
|
|
||||||
<li><strong>📊 Total Rows:</strong> <?= $rowCount ?></li>
|
|
||||||
<li><strong>📐 Average Row Size:</strong> <?= $avgRowMb ?> MB</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<form method="post">
|
|
||||||
<button name="fill" value="1" type="submit">Insert 1GB into DB</button>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,61 +2,34 @@ use harmony::{
|
|||||||
data::Version,
|
data::Version,
|
||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
maestro::Maestro,
|
maestro::Maestro,
|
||||||
modules::{
|
modules::lamp::{LAMPConfig, LAMPProfile, LAMPScore},
|
||||||
lamp::{LAMPConfig, LAMPScore},
|
|
||||||
monitoring::monitoring_alerting::{
|
|
||||||
AlertChannel, MonitoringAlertingStackScore, WebhookServiceType,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
topology::{K8sAnywhereTopology, Url},
|
topology::{K8sAnywhereTopology, Url},
|
||||||
};
|
};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// This here is the whole configuration to
|
// let _ = env_logger::Builder::from_default_env().filter_level(log::LevelFilter::Info).try_init();
|
||||||
// - setup a local K3D cluster
|
|
||||||
// - Build a docker image with the PHP project builtin and production grade settings
|
|
||||||
// - Deploy a mariadb database using a production grade helm chart
|
|
||||||
// - Deploy the new container using a kubernetes deployment
|
|
||||||
// - Configure networking between the PHP container and the database
|
|
||||||
// - Provision a public route and an SSL certificate automatically on production environments
|
|
||||||
//
|
|
||||||
// Enjoy :)
|
|
||||||
let lamp_stack = LAMPScore {
|
let lamp_stack = LAMPScore {
|
||||||
name: "harmony-lamp-demo".to_string(),
|
name: "harmony-lamp-demo".to_string(),
|
||||||
domain: Url::Url(url::Url::parse("https://lampdemo.harmony.nationtech.io").unwrap()),
|
domain: Url::Url(url::Url::parse("https://lampdemo.harmony.nationtech.io").unwrap()),
|
||||||
php_version: Version::from("8.4.4").unwrap(),
|
php_version: Version::from("8.4.4").unwrap(),
|
||||||
// This config can be extended as needed for more complicated configurations
|
|
||||||
config: LAMPConfig {
|
config: LAMPConfig {
|
||||||
project_root: "./php".into(),
|
project_root: "./php".into(),
|
||||||
database_size: format!("4Gi").into(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
profiles: HashMap::from([
|
||||||
|
("dev", LAMPProfile { ssl_enabled: false }),
|
||||||
|
("prod", LAMPProfile { ssl_enabled: true }),
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
// You can choose the type of Topology you want, we suggest starting with the
|
|
||||||
// K8sAnywhereTopology as it is the most automatic one that enables you to easily deploy
|
|
||||||
// locally, to development environment from a CI, to staging, and to production with settings
|
|
||||||
// that automatically adapt to each environment grade.
|
|
||||||
let mut maestro = Maestro::<K8sAnywhereTopology>::initialize(
|
let mut maestro = Maestro::<K8sAnywhereTopology>::initialize(
|
||||||
Inventory::autoload(),
|
Inventory::autoload(),
|
||||||
K8sAnywhereTopology::new(),
|
K8sAnywhereTopology::new(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
maestro.register_all(vec![Box::new(lamp_stack)]);
|
||||||
let url = url::Url::parse("https://discord.com/api/webhooks/dummy_channel/dummy_token")
|
harmony_tui::init(maestro).await.unwrap();
|
||||||
.expect("invalid URL");
|
|
||||||
|
|
||||||
let mut monitoring_stack_score = MonitoringAlertingStackScore::new();
|
|
||||||
monitoring_stack_score.namespace = Some(lamp_stack.config.namespace.clone());
|
|
||||||
monitoring_stack_score.alert_channel = Some(AlertChannel::WebHookUrl {
|
|
||||||
url: url,
|
|
||||||
webhook_service_type: WebhookServiceType::Discord,
|
|
||||||
});
|
|
||||||
|
|
||||||
maestro.register_all(vec![Box::new(lamp_stack), Box::new(monitoring_stack_score)]);
|
|
||||||
// Here we bootstrap the CLI, this gives some nice features if you need them
|
|
||||||
harmony_cli::init(maestro, None).await.unwrap();
|
|
||||||
}
|
}
|
||||||
// That's it, end of the infra as code.
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
helm install --create-namespace --namespace rook-ceph rook-ceph-cluster \
|
|
||||||
--set operatorNamespace=rook-ceph rook-release/rook-ceph-cluster -f values.yaml
|
|
||||||
@@ -1,721 +0,0 @@
|
|||||||
# Default values for a single rook-ceph cluster
|
|
||||||
# This is a YAML-formatted file.
|
|
||||||
# Declare variables to be passed into your templates.
|
|
||||||
|
|
||||||
# -- Namespace of the main rook operator
|
|
||||||
operatorNamespace: rook-ceph
|
|
||||||
|
|
||||||
# -- The metadata.name of the CephCluster CR
|
|
||||||
# @default -- The same as the namespace
|
|
||||||
clusterName:
|
|
||||||
|
|
||||||
# -- Optional override of the target kubernetes version
|
|
||||||
kubeVersion:
|
|
||||||
|
|
||||||
# -- Cluster ceph.conf override
|
|
||||||
configOverride:
|
|
||||||
# configOverride: |
|
|
||||||
# [global]
|
|
||||||
# mon_allow_pool_delete = true
|
|
||||||
# osd_pool_default_size = 3
|
|
||||||
# osd_pool_default_min_size = 2
|
|
||||||
|
|
||||||
# Installs a debugging toolbox deployment
|
|
||||||
toolbox:
|
|
||||||
# -- Enable Ceph debugging pod deployment. See [toolbox](../Troubleshooting/ceph-toolbox.md)
|
|
||||||
enabled: true
|
|
||||||
# -- Toolbox image, defaults to the image used by the Ceph cluster
|
|
||||||
image: #quay.io/ceph/ceph:v19.2.2
|
|
||||||
# -- Toolbox tolerations
|
|
||||||
tolerations: []
|
|
||||||
# -- Toolbox affinity
|
|
||||||
affinity: {}
|
|
||||||
# -- Toolbox container security context
|
|
||||||
containerSecurityContext:
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 2016
|
|
||||||
runAsGroup: 2016
|
|
||||||
capabilities:
|
|
||||||
drop: ["ALL"]
|
|
||||||
# -- Toolbox resources
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: "1Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "100m"
|
|
||||||
memory: "128Mi"
|
|
||||||
# -- Set the priority class for the toolbox if desired
|
|
||||||
priorityClassName:
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
# -- Enable Prometheus integration, will also create necessary RBAC rules to allow Operator to create ServiceMonitors.
|
|
||||||
# Monitoring requires Prometheus to be pre-installed
|
|
||||||
enabled: false
|
|
||||||
# -- Whether to disable the metrics reported by Ceph. If false, the prometheus mgr module and Ceph exporter are enabled
|
|
||||||
metricsDisabled: false
|
|
||||||
# -- Whether to create the Prometheus rules for Ceph alerts
|
|
||||||
createPrometheusRules: false
|
|
||||||
# -- The namespace in which to create the prometheus rules, if different from the rook cluster namespace.
|
|
||||||
# If you have multiple rook-ceph clusters in the same k8s cluster, choose the same namespace (ideally, namespace with prometheus
|
|
||||||
# deployed) to set rulesNamespaceOverride for all the clusters. Otherwise, you will get duplicate alerts with multiple alert definitions.
|
|
||||||
rulesNamespaceOverride:
|
|
||||||
# Monitoring settings for external clusters:
|
|
||||||
# externalMgrEndpoints: <list of endpoints>
|
|
||||||
# externalMgrPrometheusPort: <port>
|
|
||||||
# Scrape interval for prometheus
|
|
||||||
# interval: 10s
|
|
||||||
# allow adding custom labels and annotations to the prometheus rule
|
|
||||||
prometheusRule:
|
|
||||||
# -- Labels applied to PrometheusRule
|
|
||||||
labels: {}
|
|
||||||
# -- Annotations applied to PrometheusRule
|
|
||||||
annotations: {}
|
|
||||||
|
|
||||||
# -- Create & use PSP resources. Set this to the same value as the rook-ceph chart.
|
|
||||||
pspEnable: false
|
|
||||||
|
|
||||||
# imagePullSecrets option allow to pull docker images from private docker registry. Option will be passed to all service accounts.
|
|
||||||
# imagePullSecrets:
|
|
||||||
# - name: my-registry-secret
|
|
||||||
|
|
||||||
# All values below are taken from the CephCluster CRD
|
|
||||||
# -- Cluster configuration.
|
|
||||||
# @default -- See [below](#ceph-cluster-spec)
|
|
||||||
cephClusterSpec:
|
|
||||||
# This cluster spec example is for a converged cluster where all the Ceph daemons are running locally,
|
|
||||||
# as in the host-based example (cluster.yaml). For a different configuration such as a
|
|
||||||
# PVC-based cluster (cluster-on-pvc.yaml), external cluster (cluster-external.yaml),
|
|
||||||
# or stretch cluster (cluster-stretched.yaml), replace this entire `cephClusterSpec`
|
|
||||||
# with the specs from those examples.
|
|
||||||
|
|
||||||
# For more details, check https://rook.io/docs/rook/v1.10/CRDs/Cluster/ceph-cluster-crd/
|
|
||||||
cephVersion:
|
|
||||||
# The container image used to launch the Ceph daemon pods (mon, mgr, osd, mds, rgw).
|
|
||||||
# v18 is Reef, v19 is Squid
|
|
||||||
# RECOMMENDATION: In production, use a specific version tag instead of the general v18 flag, which pulls the latest release and could result in different
|
|
||||||
# versions running within the cluster. See tags available at https://hub.docker.com/r/ceph/ceph/tags/.
|
|
||||||
# If you want to be more precise, you can always use a timestamp tag such as quay.io/ceph/ceph:v19.2.2-20250409
|
|
||||||
# This tag might not contain a new Ceph version, just security fixes from the underlying operating system, which will reduce vulnerabilities
|
|
||||||
image: quay.io/ceph/ceph:v19.2.2
|
|
||||||
# Whether to allow unsupported versions of Ceph. Currently Reef and Squid are supported.
|
|
||||||
# Future versions such as Tentacle (v20) would require this to be set to `true`.
|
|
||||||
# Do not set to true in production.
|
|
||||||
allowUnsupported: false
|
|
||||||
|
|
||||||
# The path on the host where configuration files will be persisted. Must be specified. If there are multiple clusters, the directory must be unique for each cluster.
|
|
||||||
# Important: if you reinstall the cluster, make sure you delete this directory from each host or else the mons will fail to start on the new cluster.
|
|
||||||
# In Minikube, the '/data' directory is configured to persist across reboots. Use "/data/rook" in Minikube environment.
|
|
||||||
dataDirHostPath: /var/lib/rook
|
|
||||||
|
|
||||||
# Whether or not upgrade should continue even if a check fails
|
|
||||||
# This means Ceph's status could be degraded and we don't recommend upgrading but you might decide otherwise
|
|
||||||
# Use at your OWN risk
|
|
||||||
# To understand Rook's upgrade process of Ceph, read https://rook.io/docs/rook/v1.10/Upgrade/ceph-upgrade/
|
|
||||||
skipUpgradeChecks: false
|
|
||||||
|
|
||||||
# Whether or not continue if PGs are not clean during an upgrade
|
|
||||||
continueUpgradeAfterChecksEvenIfNotHealthy: false
|
|
||||||
|
|
||||||
# WaitTimeoutForHealthyOSDInMinutes defines the time (in minutes) the operator would wait before an OSD can be stopped for upgrade or restart.
|
|
||||||
# If the timeout exceeds and OSD is not ok to stop, then the operator would skip upgrade for the current OSD and proceed with the next one
|
|
||||||
# if `continueUpgradeAfterChecksEvenIfNotHealthy` is `false`. If `continueUpgradeAfterChecksEvenIfNotHealthy` is `true`, then operator would
|
|
||||||
# continue with the upgrade of an OSD even if its not ok to stop after the timeout. This timeout won't be applied if `skipUpgradeChecks` is `true`.
|
|
||||||
# The default wait timeout is 10 minutes.
|
|
||||||
waitTimeoutForHealthyOSDInMinutes: 10
|
|
||||||
|
|
||||||
# Whether or not requires PGs are clean before an OSD upgrade. If set to `true` OSD upgrade process won't start until PGs are healthy.
|
|
||||||
# This configuration will be ignored if `skipUpgradeChecks` is `true`.
|
|
||||||
# Default is false.
|
|
||||||
upgradeOSDRequiresHealthyPGs: false
|
|
||||||
|
|
||||||
mon:
|
|
||||||
# Set the number of mons to be started. Generally recommended to be 3.
|
|
||||||
# For highest availability, an odd number of mons should be specified.
|
|
||||||
count: 3
|
|
||||||
# The mons should be on unique nodes. For production, at least 3 nodes are recommended for this reason.
|
|
||||||
# Mons should only be allowed on the same node for test environments where data loss is acceptable.
|
|
||||||
allowMultiplePerNode: false
|
|
||||||
|
|
||||||
mgr:
|
|
||||||
# When higher availability of the mgr is needed, increase the count to 2.
|
|
||||||
# In that case, one mgr will be active and one in standby. When Ceph updates which
|
|
||||||
# mgr is active, Rook will update the mgr services to match the active mgr.
|
|
||||||
count: 2
|
|
||||||
allowMultiplePerNode: false
|
|
||||||
modules:
|
|
||||||
# List of modules to optionally enable or disable.
|
|
||||||
# Note the "dashboard" and "monitoring" modules are already configured by other settings in the cluster CR.
|
|
||||||
# - name: rook
|
|
||||||
# enabled: true
|
|
||||||
|
|
||||||
# enable the ceph dashboard for viewing cluster status
|
|
||||||
dashboard:
|
|
||||||
enabled: true
|
|
||||||
# serve the dashboard under a subpath (useful when you are accessing the dashboard via a reverse proxy)
|
|
||||||
# urlPrefix: /ceph-dashboard
|
|
||||||
# serve the dashboard at the given port.
|
|
||||||
# port: 8443
|
|
||||||
# Serve the dashboard using SSL (if using ingress to expose the dashboard and `ssl: true` you need to set
|
|
||||||
# the corresponding "backend protocol" annotation(s) for your ingress controller of choice)
|
|
||||||
ssl: true
|
|
||||||
|
|
||||||
# Network configuration, see: https://github.com/rook/rook/blob/master/Documentation/CRDs/Cluster/ceph-cluster-crd.md#network-configuration-settings
|
|
||||||
network:
|
|
||||||
connections:
|
|
||||||
# Whether to encrypt the data in transit across the wire to prevent eavesdropping the data on the network.
|
|
||||||
# The default is false. When encryption is enabled, all communication between clients and Ceph daemons, or between Ceph daemons will be encrypted.
|
|
||||||
# When encryption is not enabled, clients still establish a strong initial authentication and data integrity is still validated with a crc check.
|
|
||||||
# IMPORTANT: Encryption requires the 5.11 kernel for the latest nbd and cephfs drivers. Alternatively for testing only,
|
|
||||||
# you can set the "mounter: rbd-nbd" in the rbd storage class, or "mounter: fuse" in the cephfs storage class.
|
|
||||||
# The nbd and fuse drivers are *not* recommended in production since restarting the csi driver pod will disconnect the volumes.
|
|
||||||
encryption:
|
|
||||||
enabled: false
|
|
||||||
# Whether to compress the data in transit across the wire. The default is false.
|
|
||||||
# The kernel requirements above for encryption also apply to compression.
|
|
||||||
compression:
|
|
||||||
enabled: false
|
|
||||||
# Whether to require communication over msgr2. If true, the msgr v1 port (6789) will be disabled
|
|
||||||
# and clients will be required to connect to the Ceph cluster with the v2 port (3300).
|
|
||||||
# Requires a kernel that supports msgr v2 (kernel 5.11 or CentOS 8.4 or newer).
|
|
||||||
requireMsgr2: false
|
|
||||||
# # enable host networking
|
|
||||||
# provider: host
|
|
||||||
# # EXPERIMENTAL: enable the Multus network provider
|
|
||||||
# provider: multus
|
|
||||||
# selectors:
|
|
||||||
# # The selector keys are required to be `public` and `cluster`.
|
|
||||||
# # Based on the configuration, the operator will do the following:
|
|
||||||
# # 1. if only the `public` selector key is specified both public_network and cluster_network Ceph settings will listen on that interface
|
|
||||||
# # 2. if both `public` and `cluster` selector keys are specified the first one will point to 'public_network' flag and the second one to 'cluster_network'
|
|
||||||
# #
|
|
||||||
# # In order to work, each selector value must match a NetworkAttachmentDefinition object in Multus
|
|
||||||
# #
|
|
||||||
# # public: public-conf --> NetworkAttachmentDefinition object name in Multus
|
|
||||||
# # cluster: cluster-conf --> NetworkAttachmentDefinition object name in Multus
|
|
||||||
# # Provide internet protocol version. IPv6, IPv4 or empty string are valid options. Empty string would mean IPv4
|
|
||||||
# ipFamily: "IPv6"
|
|
||||||
# # Ceph daemons to listen on both IPv4 and Ipv6 networks
|
|
||||||
# dualStack: false
|
|
||||||
|
|
||||||
# enable the crash collector for ceph daemon crash collection
|
|
||||||
crashCollector:
|
|
||||||
disable: false
|
|
||||||
# Uncomment daysToRetain to prune ceph crash entries older than the
|
|
||||||
# specified number of days.
|
|
||||||
# daysToRetain: 30
|
|
||||||
|
|
||||||
# enable log collector, daemons will log on files and rotate
|
|
||||||
logCollector:
|
|
||||||
enabled: true
|
|
||||||
periodicity: daily # one of: hourly, daily, weekly, monthly
|
|
||||||
maxLogSize: 500M # SUFFIX may be 'M' or 'G'. Must be at least 1M.
|
|
||||||
|
|
||||||
# automate [data cleanup process](https://github.com/rook/rook/blob/master/Documentation/Storage-Configuration/ceph-teardown.md#delete-the-data-on-hosts) in cluster destruction.
|
|
||||||
cleanupPolicy:
|
|
||||||
# Since cluster cleanup is destructive to data, confirmation is required.
|
|
||||||
# To destroy all Rook data on hosts during uninstall, confirmation must be set to "yes-really-destroy-data".
|
|
||||||
# This value should only be set when the cluster is about to be deleted. After the confirmation is set,
|
|
||||||
# Rook will immediately stop configuring the cluster and only wait for the delete command.
|
|
||||||
# If the empty string is set, Rook will not destroy any data on hosts during uninstall.
|
|
||||||
confirmation: ""
|
|
||||||
# sanitizeDisks represents settings for sanitizing OSD disks on cluster deletion
|
|
||||||
sanitizeDisks:
|
|
||||||
# method indicates if the entire disk should be sanitized or simply ceph's metadata
|
|
||||||
# in both case, re-install is possible
|
|
||||||
# possible choices are 'complete' or 'quick' (default)
|
|
||||||
method: quick
|
|
||||||
# dataSource indicate where to get random bytes from to write on the disk
|
|
||||||
# possible choices are 'zero' (default) or 'random'
|
|
||||||
# using random sources will consume entropy from the system and will take much more time then the zero source
|
|
||||||
dataSource: zero
|
|
||||||
# iteration overwrite N times instead of the default (1)
|
|
||||||
# takes an integer value
|
|
||||||
iteration: 1
|
|
||||||
# allowUninstallWithVolumes defines how the uninstall should be performed
|
|
||||||
# If set to true, cephCluster deletion does not wait for the PVs to be deleted.
|
|
||||||
allowUninstallWithVolumes: false
|
|
||||||
|
|
||||||
# To control where various services will be scheduled by kubernetes, use the placement configuration sections below.
|
|
||||||
# The example under 'all' would have all services scheduled on kubernetes nodes labeled with 'role=storage-node' and
|
|
||||||
# tolerate taints with a key of 'storage-node'.
|
|
||||||
# placement:
|
|
||||||
# all:
|
|
||||||
# nodeAffinity:
|
|
||||||
# requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
# nodeSelectorTerms:
|
|
||||||
# - matchExpressions:
|
|
||||||
# - key: role
|
|
||||||
# operator: In
|
|
||||||
# values:
|
|
||||||
# - storage-node
|
|
||||||
# podAffinity:
|
|
||||||
# podAntiAffinity:
|
|
||||||
# topologySpreadConstraints:
|
|
||||||
# tolerations:
|
|
||||||
# - key: storage-node
|
|
||||||
# operator: Exists
|
|
||||||
# # The above placement information can also be specified for mon, osd, and mgr components
|
|
||||||
# mon:
|
|
||||||
# # Monitor deployments may contain an anti-affinity rule for avoiding monitor
|
|
||||||
# # collocation on the same node. This is a required rule when host network is used
|
|
||||||
# # or when AllowMultiplePerNode is false. Otherwise this anti-affinity rule is a
|
|
||||||
# # preferred rule with weight: 50.
|
|
||||||
# osd:
|
|
||||||
# mgr:
|
|
||||||
# cleanup:
|
|
||||||
|
|
||||||
# annotations:
|
|
||||||
# all:
|
|
||||||
# mon:
|
|
||||||
# osd:
|
|
||||||
# cleanup:
|
|
||||||
# prepareosd:
|
|
||||||
# # If no mgr annotations are set, prometheus scrape annotations will be set by default.
|
|
||||||
# mgr:
|
|
||||||
# dashboard:
|
|
||||||
|
|
||||||
# labels:
|
|
||||||
# all:
|
|
||||||
# mon:
|
|
||||||
# osd:
|
|
||||||
# cleanup:
|
|
||||||
# mgr:
|
|
||||||
# prepareosd:
|
|
||||||
# # monitoring is a list of key-value pairs. It is injected into all the monitoring resources created by operator.
|
|
||||||
# # These labels can be passed as LabelSelector to Prometheus
|
|
||||||
# monitoring:
|
|
||||||
# dashboard:
|
|
||||||
|
|
||||||
resources:
|
|
||||||
mgr:
|
|
||||||
limits:
|
|
||||||
memory: "1Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "500m"
|
|
||||||
memory: "512Mi"
|
|
||||||
mon:
|
|
||||||
limits:
|
|
||||||
memory: "2Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "1000m"
|
|
||||||
memory: "1Gi"
|
|
||||||
osd:
|
|
||||||
limits:
|
|
||||||
memory: "4Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "1000m"
|
|
||||||
memory: "4Gi"
|
|
||||||
prepareosd:
|
|
||||||
# limits: It is not recommended to set limits on the OSD prepare job
|
|
||||||
# since it's a one-time burst for memory that must be allowed to
|
|
||||||
# complete without an OOM kill. Note however that if a k8s
|
|
||||||
# limitRange guardrail is defined external to Rook, the lack of
|
|
||||||
# a limit here may result in a sync failure, in which case a
|
|
||||||
# limit should be added. 1200Mi may suffice for up to 15Ti
|
|
||||||
# OSDs ; for larger devices 2Gi may be required.
|
|
||||||
# cf. https://github.com/rook/rook/pull/11103
|
|
||||||
requests:
|
|
||||||
cpu: "500m"
|
|
||||||
memory: "50Mi"
|
|
||||||
mgr-sidecar:
|
|
||||||
limits:
|
|
||||||
memory: "100Mi"
|
|
||||||
requests:
|
|
||||||
cpu: "100m"
|
|
||||||
memory: "40Mi"
|
|
||||||
crashcollector:
|
|
||||||
limits:
|
|
||||||
memory: "60Mi"
|
|
||||||
requests:
|
|
||||||
cpu: "100m"
|
|
||||||
memory: "60Mi"
|
|
||||||
logcollector:
|
|
||||||
limits:
|
|
||||||
memory: "1Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "100m"
|
|
||||||
memory: "100Mi"
|
|
||||||
cleanup:
|
|
||||||
limits:
|
|
||||||
memory: "1Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "500m"
|
|
||||||
memory: "100Mi"
|
|
||||||
exporter:
|
|
||||||
limits:
|
|
||||||
memory: "128Mi"
|
|
||||||
requests:
|
|
||||||
cpu: "50m"
|
|
||||||
memory: "50Mi"
|
|
||||||
|
|
||||||
# The option to automatically remove OSDs that are out and are safe to destroy.
|
|
||||||
removeOSDsIfOutAndSafeToRemove: false
|
|
||||||
|
|
||||||
# priority classes to apply to ceph resources
|
|
||||||
priorityClassNames:
|
|
||||||
mon: system-node-critical
|
|
||||||
osd: system-node-critical
|
|
||||||
mgr: system-cluster-critical
|
|
||||||
|
|
||||||
storage: # cluster level storage configuration and selection
|
|
||||||
useAllNodes: true
|
|
||||||
useAllDevices: true
|
|
||||||
# deviceFilter:
|
|
||||||
# config:
|
|
||||||
# crushRoot: "custom-root" # specify a non-default root label for the CRUSH map
|
|
||||||
# metadataDevice: "md0" # specify a non-rotational storage so ceph-volume will use it as block db device of bluestore.
|
|
||||||
# databaseSizeMB: "1024" # uncomment if the disks are smaller than 100 GB
|
|
||||||
# osdsPerDevice: "1" # this value can be overridden at the node or device level
|
|
||||||
# encryptedDevice: "true" # the default value for this option is "false"
|
|
||||||
# # Individual nodes and their config can be specified as well, but 'useAllNodes' above must be set to false. Then, only the named
|
|
||||||
# # nodes below will be used as storage resources. Each node's 'name' field should match their 'kubernetes.io/hostname' label.
|
|
||||||
# nodes:
|
|
||||||
# - name: "172.17.4.201"
|
|
||||||
# devices: # specific devices to use for storage can be specified for each node
|
|
||||||
# - name: "sdb"
|
|
||||||
# - name: "nvme01" # multiple osds can be created on high performance devices
|
|
||||||
# config:
|
|
||||||
# osdsPerDevice: "5"
|
|
||||||
# - name: "/dev/disk/by-id/ata-ST4000DM004-XXXX" # devices can be specified using full udev paths
|
|
||||||
# config: # configuration can be specified at the node level which overrides the cluster level config
|
|
||||||
# - name: "172.17.4.301"
|
|
||||||
# deviceFilter: "^sd."
|
|
||||||
|
|
||||||
# The section for configuring management of daemon disruptions during upgrade or fencing.
|
|
||||||
disruptionManagement:
|
|
||||||
# If true, the operator will create and manage PodDisruptionBudgets for OSD, Mon, RGW, and MDS daemons. OSD PDBs are managed dynamically
|
|
||||||
# via the strategy outlined in the [design](https://github.com/rook/rook/blob/master/design/ceph/ceph-managed-disruptionbudgets.md). The operator will
|
|
||||||
# block eviction of OSDs by default and unblock them safely when drains are detected.
|
|
||||||
managePodBudgets: true
|
|
||||||
# A duration in minutes that determines how long an entire failureDomain like `region/zone/host` will be held in `noout` (in addition to the
|
|
||||||
# default DOWN/OUT interval) when it is draining. This is only relevant when `managePodBudgets` is `true`. The default value is `30` minutes.
|
|
||||||
osdMaintenanceTimeout: 30
|
|
||||||
|
|
||||||
# Configure the healthcheck and liveness probes for ceph pods.
|
|
||||||
# Valid values for daemons are 'mon', 'osd', 'status'
|
|
||||||
healthCheck:
|
|
||||||
daemonHealth:
|
|
||||||
mon:
|
|
||||||
disabled: false
|
|
||||||
interval: 45s
|
|
||||||
osd:
|
|
||||||
disabled: false
|
|
||||||
interval: 60s
|
|
||||||
status:
|
|
||||||
disabled: false
|
|
||||||
interval: 60s
|
|
||||||
# Change pod liveness probe, it works for all mon, mgr, and osd pods.
|
|
||||||
livenessProbe:
|
|
||||||
mon:
|
|
||||||
disabled: false
|
|
||||||
mgr:
|
|
||||||
disabled: false
|
|
||||||
osd:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
# -- Enable an ingress for the ceph-dashboard
|
|
||||||
dashboard:
|
|
||||||
# {}
|
|
||||||
# labels:
|
|
||||||
# external-dns/private: "true"
|
|
||||||
annotations:
|
|
||||||
"route.openshift.io/termination": "passthrough"
|
|
||||||
# external-dns.alpha.kubernetes.io/hostname: dashboard.example.com
|
|
||||||
# nginx.ingress.kubernetes.io/rewrite-target: /ceph-dashboard/$2
|
|
||||||
# If the dashboard has ssl: true the following will make sure the NGINX Ingress controller can expose the dashboard correctly
|
|
||||||
# nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
|
|
||||||
# nginx.ingress.kubernetes.io/server-snippet: |
|
|
||||||
# proxy_ssl_verify off;
|
|
||||||
host:
|
|
||||||
name: ceph.apps.ncd0.harmony.mcd
|
|
||||||
path: null # TODO the chart does not allow removing the path, and it causes openshift to fail creating a route, because path is not supported with termination mode passthrough
|
|
||||||
pathType: ImplementationSpecific
|
|
||||||
tls:
|
|
||||||
- {}
|
|
||||||
# secretName: testsecret-tls
|
|
||||||
# Note: Only one of ingress class annotation or the `ingressClassName:` can be used at a time
|
|
||||||
# to set the ingress class
|
|
||||||
# ingressClassName: openshift-default
|
|
||||||
# labels:
|
|
||||||
# external-dns/private: "true"
|
|
||||||
# annotations:
|
|
||||||
# external-dns.alpha.kubernetes.io/hostname: dashboard.example.com
|
|
||||||
# nginx.ingress.kubernetes.io/rewrite-target: /ceph-dashboard/$2
|
|
||||||
# If the dashboard has ssl: true the following will make sure the NGINX Ingress controller can expose the dashboard correctly
|
|
||||||
# nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
|
|
||||||
# nginx.ingress.kubernetes.io/server-snippet: |
|
|
||||||
# proxy_ssl_verify off;
|
|
||||||
# host:
|
|
||||||
# name: dashboard.example.com
|
|
||||||
# path: "/ceph-dashboard(/|$)(.*)"
|
|
||||||
# pathType: Prefix
|
|
||||||
# tls:
|
|
||||||
# - hosts:
|
|
||||||
# - dashboard.example.com
|
|
||||||
# secretName: testsecret-tls
|
|
||||||
## Note: Only one of ingress class annotation or the `ingressClassName:` can be used at a time
|
|
||||||
## to set the ingress class
|
|
||||||
# ingressClassName: nginx
|
|
||||||
|
|
||||||
# -- A list of CephBlockPool configurations to deploy
|
|
||||||
# @default -- See [below](#ceph-block-pools)
|
|
||||||
cephBlockPools:
|
|
||||||
- name: ceph-blockpool
|
|
||||||
# see https://github.com/rook/rook/blob/master/Documentation/CRDs/Block-Storage/ceph-block-pool-crd.md#spec for available configuration
|
|
||||||
spec:
|
|
||||||
failureDomain: host
|
|
||||||
replicated:
|
|
||||||
size: 3
|
|
||||||
# Enables collecting RBD per-image IO statistics by enabling dynamic OSD performance counters. Defaults to false.
|
|
||||||
# For reference: https://docs.ceph.com/docs/latest/mgr/prometheus/#rbd-io-statistics
|
|
||||||
# enableRBDStats: true
|
|
||||||
storageClass:
|
|
||||||
enabled: true
|
|
||||||
name: ceph-block
|
|
||||||
annotations: {}
|
|
||||||
labels: {}
|
|
||||||
isDefault: true
|
|
||||||
reclaimPolicy: Delete
|
|
||||||
allowVolumeExpansion: true
|
|
||||||
volumeBindingMode: "Immediate"
|
|
||||||
mountOptions: []
|
|
||||||
# see https://kubernetes.io/docs/concepts/storage/storage-classes/#allowed-topologies
|
|
||||||
allowedTopologies: []
|
|
||||||
# - matchLabelExpressions:
|
|
||||||
# - key: rook-ceph-role
|
|
||||||
# values:
|
|
||||||
# - storage-node
|
|
||||||
# see https://github.com/rook/rook/blob/master/Documentation/Storage-Configuration/Block-Storage-RBD/block-storage.md#provision-storage for available configuration
|
|
||||||
parameters:
|
|
||||||
# (optional) mapOptions is a comma-separated list of map options.
|
|
||||||
# For krbd options refer
|
|
||||||
# https://docs.ceph.com/docs/latest/man/8/rbd/#kernel-rbd-krbd-options
|
|
||||||
# For nbd options refer
|
|
||||||
# https://docs.ceph.com/docs/latest/man/8/rbd-nbd/#options
|
|
||||||
# mapOptions: lock_on_read,queue_depth=1024
|
|
||||||
|
|
||||||
# (optional) unmapOptions is a comma-separated list of unmap options.
|
|
||||||
# For krbd options refer
|
|
||||||
# https://docs.ceph.com/docs/latest/man/8/rbd/#kernel-rbd-krbd-options
|
|
||||||
# For nbd options refer
|
|
||||||
# https://docs.ceph.com/docs/latest/man/8/rbd-nbd/#options
|
|
||||||
# unmapOptions: force
|
|
||||||
|
|
||||||
# RBD image format. Defaults to "2".
|
|
||||||
imageFormat: "2"
|
|
||||||
|
|
||||||
# RBD image features, equivalent to OR'd bitfield value: 63
|
|
||||||
# Available for imageFormat: "2". Older releases of CSI RBD
|
|
||||||
# support only the `layering` feature. The Linux kernel (KRBD) supports the
|
|
||||||
# full feature complement as of 5.4
|
|
||||||
imageFeatures: layering
|
|
||||||
|
|
||||||
# These secrets contain Ceph admin credentials.
|
|
||||||
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
|
|
||||||
csi.storage.k8s.io/provisioner-secret-namespace: "{{ .Release.Namespace }}"
|
|
||||||
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
|
|
||||||
csi.storage.k8s.io/controller-expand-secret-namespace: "{{ .Release.Namespace }}"
|
|
||||||
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
|
|
||||||
csi.storage.k8s.io/node-stage-secret-namespace: "{{ .Release.Namespace }}"
|
|
||||||
# Specify the filesystem type of the volume. If not specified, csi-provisioner
|
|
||||||
# will set default as `ext4`. Note that `xfs` is not recommended due to potential deadlock
|
|
||||||
# in hyperconverged settings where the volume is mounted on the same node as the osds.
|
|
||||||
csi.storage.k8s.io/fstype: ext4
|
|
||||||
|
|
||||||
# -- A list of CephFileSystem configurations to deploy
|
|
||||||
# @default -- See [below](#ceph-file-systems)
|
|
||||||
cephFileSystems:
|
|
||||||
- name: ceph-filesystem
|
|
||||||
# see https://github.com/rook/rook/blob/master/Documentation/CRDs/Shared-Filesystem/ceph-filesystem-crd.md#filesystem-settings for available configuration
|
|
||||||
spec:
|
|
||||||
metadataPool:
|
|
||||||
replicated:
|
|
||||||
size: 3
|
|
||||||
dataPools:
|
|
||||||
- failureDomain: host
|
|
||||||
replicated:
|
|
||||||
size: 3
|
|
||||||
# Optional and highly recommended, 'data0' by default, see https://github.com/rook/rook/blob/master/Documentation/CRDs/Shared-Filesystem/ceph-filesystem-crd.md#pools
|
|
||||||
name: data0
|
|
||||||
metadataServer:
|
|
||||||
activeCount: 1
|
|
||||||
activeStandby: true
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: "4Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "1000m"
|
|
||||||
memory: "4Gi"
|
|
||||||
priorityClassName: system-cluster-critical
|
|
||||||
storageClass:
|
|
||||||
enabled: true
|
|
||||||
isDefault: false
|
|
||||||
name: ceph-filesystem
|
|
||||||
# (Optional) specify a data pool to use, must be the name of one of the data pools above, 'data0' by default
|
|
||||||
pool: data0
|
|
||||||
reclaimPolicy: Delete
|
|
||||||
allowVolumeExpansion: true
|
|
||||||
volumeBindingMode: "Immediate"
|
|
||||||
annotations: {}
|
|
||||||
labels: {}
|
|
||||||
mountOptions: []
|
|
||||||
# see https://github.com/rook/rook/blob/master/Documentation/Storage-Configuration/Shared-Filesystem-CephFS/filesystem-storage.md#provision-storage for available configuration
|
|
||||||
parameters:
|
|
||||||
# The secrets contain Ceph admin credentials.
|
|
||||||
csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
|
|
||||||
csi.storage.k8s.io/provisioner-secret-namespace: "{{ .Release.Namespace }}"
|
|
||||||
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
|
|
||||||
csi.storage.k8s.io/controller-expand-secret-namespace: "{{ .Release.Namespace }}"
|
|
||||||
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
|
|
||||||
csi.storage.k8s.io/node-stage-secret-namespace: "{{ .Release.Namespace }}"
|
|
||||||
# Specify the filesystem type of the volume. If not specified, csi-provisioner
|
|
||||||
# will set default as `ext4`. Note that `xfs` is not recommended due to potential deadlock
|
|
||||||
# in hyperconverged settings where the volume is mounted on the same node as the osds.
|
|
||||||
csi.storage.k8s.io/fstype: ext4
|
|
||||||
|
|
||||||
# -- Settings for the filesystem snapshot class
|
|
||||||
# @default -- See [CephFS Snapshots](../Storage-Configuration/Ceph-CSI/ceph-csi-snapshot.md#cephfs-snapshots)
|
|
||||||
cephFileSystemVolumeSnapshotClass:
|
|
||||||
enabled: false
|
|
||||||
name: ceph-filesystem
|
|
||||||
isDefault: true
|
|
||||||
deletionPolicy: Delete
|
|
||||||
annotations: {}
|
|
||||||
labels: {}
|
|
||||||
# see https://rook.io/docs/rook/v1.10/Storage-Configuration/Ceph-CSI/ceph-csi-snapshot/#cephfs-snapshots for available configuration
|
|
||||||
parameters: {}
|
|
||||||
|
|
||||||
# -- Settings for the block pool snapshot class
|
|
||||||
# @default -- See [RBD Snapshots](../Storage-Configuration/Ceph-CSI/ceph-csi-snapshot.md#rbd-snapshots)
|
|
||||||
cephBlockPoolsVolumeSnapshotClass:
|
|
||||||
enabled: false
|
|
||||||
name: ceph-block
|
|
||||||
isDefault: false
|
|
||||||
deletionPolicy: Delete
|
|
||||||
annotations: {}
|
|
||||||
labels: {}
|
|
||||||
# see https://rook.io/docs/rook/v1.10/Storage-Configuration/Ceph-CSI/ceph-csi-snapshot/#rbd-snapshots for available configuration
|
|
||||||
parameters: {}
|
|
||||||
|
|
||||||
# -- A list of CephObjectStore configurations to deploy
|
|
||||||
# @default -- See [below](#ceph-object-stores)
|
|
||||||
cephObjectStores:
|
|
||||||
- name: ceph-objectstore
|
|
||||||
# see https://github.com/rook/rook/blob/master/Documentation/CRDs/Object-Storage/ceph-object-store-crd.md#object-store-settings for available configuration
|
|
||||||
spec:
|
|
||||||
metadataPool:
|
|
||||||
failureDomain: host
|
|
||||||
replicated:
|
|
||||||
size: 3
|
|
||||||
dataPool:
|
|
||||||
failureDomain: host
|
|
||||||
erasureCoded:
|
|
||||||
dataChunks: 2
|
|
||||||
codingChunks: 1
|
|
||||||
parameters:
|
|
||||||
bulk: "true"
|
|
||||||
preservePoolsOnDelete: true
|
|
||||||
gateway:
|
|
||||||
port: 80
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: "2Gi"
|
|
||||||
requests:
|
|
||||||
cpu: "1000m"
|
|
||||||
memory: "1Gi"
|
|
||||||
# securePort: 443
|
|
||||||
# sslCertificateRef:
|
|
||||||
instances: 1
|
|
||||||
priorityClassName: system-cluster-critical
|
|
||||||
# opsLogSidecar:
|
|
||||||
# resources:
|
|
||||||
# limits:
|
|
||||||
# memory: "100Mi"
|
|
||||||
# requests:
|
|
||||||
# cpu: "100m"
|
|
||||||
# memory: "40Mi"
|
|
||||||
storageClass:
|
|
||||||
enabled: true
|
|
||||||
name: ceph-bucket
|
|
||||||
reclaimPolicy: Delete
|
|
||||||
volumeBindingMode: "Immediate"
|
|
||||||
annotations: {}
|
|
||||||
labels: {}
|
|
||||||
# see https://github.com/rook/rook/blob/master/Documentation/Storage-Configuration/Object-Storage-RGW/ceph-object-bucket-claim.md#storageclass for available configuration
|
|
||||||
parameters:
|
|
||||||
# note: objectStoreNamespace and objectStoreName are configured by the chart
|
|
||||||
region: us-east-1
|
|
||||||
ingress:
|
|
||||||
# Enable an ingress for the ceph-objectstore
|
|
||||||
enabled: true
|
|
||||||
# The ingress port by default will be the object store's "securePort" (if set), or the gateway "port".
|
|
||||||
# To override those defaults, set this ingress port to the desired port.
|
|
||||||
# port: 80
|
|
||||||
# annotations: {}
|
|
||||||
host:
|
|
||||||
name: objectstore.apps.ncd0.harmony.mcd
|
|
||||||
path: /
|
|
||||||
pathType: Prefix
|
|
||||||
# tls:
|
|
||||||
# - hosts:
|
|
||||||
# - objectstore.example.com
|
|
||||||
# secretName: ceph-objectstore-tls
|
|
||||||
# ingressClassName: nginx
|
|
||||||
## cephECBlockPools are disabled by default, please remove the comments and set desired values to enable it
|
|
||||||
## For erasure coded a replicated metadata pool is required.
|
|
||||||
## https://rook.io/docs/rook/latest/CRDs/Shared-Filesystem/ceph-filesystem-crd/#erasure-coded
|
|
||||||
#cephECBlockPools:
|
|
||||||
# - name: ec-pool
|
|
||||||
# spec:
|
|
||||||
# metadataPool:
|
|
||||||
# replicated:
|
|
||||||
# size: 2
|
|
||||||
# dataPool:
|
|
||||||
# failureDomain: osd
|
|
||||||
# erasureCoded:
|
|
||||||
# dataChunks: 2
|
|
||||||
# codingChunks: 1
|
|
||||||
# deviceClass: hdd
|
|
||||||
#
|
|
||||||
# parameters:
|
|
||||||
# # clusterID is the namespace where the rook cluster is running
|
|
||||||
# # If you change this namespace, also change the namespace below where the secret namespaces are defined
|
|
||||||
# clusterID: rook-ceph # namespace:cluster
|
|
||||||
# # (optional) mapOptions is a comma-separated list of map options.
|
|
||||||
# # For krbd options refer
|
|
||||||
# # https://docs.ceph.com/docs/latest/man/8/rbd/#kernel-rbd-krbd-options
|
|
||||||
# # For nbd options refer
|
|
||||||
# # https://docs.ceph.com/docs/latest/man/8/rbd-nbd/#options
|
|
||||||
# # mapOptions: lock_on_read,queue_depth=1024
|
|
||||||
#
|
|
||||||
# # (optional) unmapOptions is a comma-separated list of unmap options.
|
|
||||||
# # For krbd options refer
|
|
||||||
# # https://docs.ceph.com/docs/latest/man/8/rbd/#kernel-rbd-krbd-options
|
|
||||||
# # For nbd options refer
|
|
||||||
# # https://docs.ceph.com/docs/latest/man/8/rbd-nbd/#options
|
|
||||||
# # unmapOptions: force
|
|
||||||
#
|
|
||||||
# # RBD image format. Defaults to "2".
|
|
||||||
# imageFormat: "2"
|
|
||||||
#
|
|
||||||
# # RBD image features, equivalent to OR'd bitfield value: 63
|
|
||||||
# # Available for imageFormat: "2". Older releases of CSI RBD
|
|
||||||
# # support only the `layering` feature. The Linux kernel (KRBD) supports the
|
|
||||||
# # full feature complement as of 5.4
|
|
||||||
# # imageFeatures: layering,fast-diff,object-map,deep-flatten,exclusive-lock
|
|
||||||
# imageFeatures: layering
|
|
||||||
#
|
|
||||||
# storageClass:
|
|
||||||
# provisioner: rook-ceph.rbd.csi.ceph.com # csi-provisioner-name
|
|
||||||
# enabled: true
|
|
||||||
# name: rook-ceph-block
|
|
||||||
# isDefault: false
|
|
||||||
# annotations: { }
|
|
||||||
# labels: { }
|
|
||||||
# allowVolumeExpansion: true
|
|
||||||
# reclaimPolicy: Delete
|
|
||||||
|
|
||||||
# -- CSI driver name prefix for cephfs, rbd and nfs.
|
|
||||||
# @default -- `namespace name where rook-ceph operator is deployed`
|
|
||||||
csiDriverNamePrefix:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
helm repo add rook-release https://charts.rook.io/release
|
|
||||||
helm install --create-namespace --namespace rook-ceph rook-ceph rook-release/rook-ceph -f values.yaml
|
|
||||||
@@ -1,674 +0,0 @@
|
|||||||
# Default values for rook-ceph-operator
|
|
||||||
# This is a YAML-formatted file.
|
|
||||||
# Declare variables to be passed into your templates.
|
|
||||||
|
|
||||||
image:
|
|
||||||
# -- Image
|
|
||||||
repository: docker.io/rook/ceph
|
|
||||||
# -- Image tag
|
|
||||||
# @default -- `master`
|
|
||||||
tag: v1.17.1
|
|
||||||
# -- Image pull policy
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
|
|
||||||
crds:
|
|
||||||
# -- Whether the helm chart should create and update the CRDs. If false, the CRDs must be
|
|
||||||
# managed independently with deploy/examples/crds.yaml.
|
|
||||||
# **WARNING** Only set during first deployment. If later disabled the cluster may be DESTROYED.
|
|
||||||
# If the CRDs are deleted in this case, see
|
|
||||||
# [the disaster recovery guide](https://rook.io/docs/rook/latest/Troubleshooting/disaster-recovery/#restoring-crds-after-deletion)
|
|
||||||
# to restore them.
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
# -- Pod resource requests & limits
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 512Mi
|
|
||||||
requests:
|
|
||||||
cpu: 200m
|
|
||||||
memory: 128Mi
|
|
||||||
|
|
||||||
# -- Kubernetes [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) to add to the Deployment.
|
|
||||||
nodeSelector: {}
|
|
||||||
# Constraint rook-ceph-operator Deployment to nodes with label `disktype: ssd`.
|
|
||||||
# For more info, see https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
|
|
||||||
# disktype: ssd
|
|
||||||
|
|
||||||
# -- List of Kubernetes [`tolerations`](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to add to the Deployment.
|
|
||||||
tolerations: []
|
|
||||||
|
|
||||||
# -- Delay to use for the `node.kubernetes.io/unreachable` pod failure toleration to override
|
|
||||||
# the Kubernetes default of 5 minutes
|
|
||||||
unreachableNodeTolerationSeconds: 5
|
|
||||||
|
|
||||||
# -- Whether the operator should watch cluster CRD in its own namespace or not
|
|
||||||
currentNamespaceOnly: false
|
|
||||||
|
|
||||||
# -- Custom pod labels for the operator
|
|
||||||
operatorPodLabels: {}
|
|
||||||
|
|
||||||
# -- Pod annotations
|
|
||||||
annotations: {}
|
|
||||||
|
|
||||||
# -- Global log level for the operator.
|
|
||||||
# Options: `ERROR`, `WARNING`, `INFO`, `DEBUG`
|
|
||||||
logLevel: INFO
|
|
||||||
|
|
||||||
# -- If true, create & use RBAC resources
|
|
||||||
rbacEnable: true
|
|
||||||
|
|
||||||
rbacAggregate:
|
|
||||||
# -- If true, create a ClusterRole aggregated to [user facing roles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) for objectbucketclaims
|
|
||||||
enableOBCs: false
|
|
||||||
|
|
||||||
# -- If true, create & use PSP resources
|
|
||||||
pspEnable: false
|
|
||||||
|
|
||||||
# -- Set the priority class for the rook operator deployment if desired
|
|
||||||
priorityClassName:
|
|
||||||
|
|
||||||
# -- Set the container security context for the operator
|
|
||||||
containerSecurityContext:
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 2016
|
|
||||||
runAsGroup: 2016
|
|
||||||
capabilities:
|
|
||||||
drop: ["ALL"]
|
|
||||||
# -- If true, loop devices are allowed to be used for osds in test clusters
|
|
||||||
allowLoopDevices: false
|
|
||||||
|
|
||||||
# Settings for whether to disable the drivers or other daemons if they are not
|
|
||||||
# needed
|
|
||||||
csi:
|
|
||||||
# -- Enable Ceph CSI RBD driver
|
|
||||||
enableRbdDriver: true
|
|
||||||
# -- Enable Ceph CSI CephFS driver
|
|
||||||
enableCephfsDriver: true
|
|
||||||
# -- Disable the CSI driver.
|
|
||||||
disableCsiDriver: "false"
|
|
||||||
|
|
||||||
# -- Enable host networking for CSI CephFS and RBD nodeplugins. This may be necessary
|
|
||||||
# in some network configurations where the SDN does not provide access to an external cluster or
|
|
||||||
# there is significant drop in read/write performance
|
|
||||||
enableCSIHostNetwork: true
|
|
||||||
# -- Enable Snapshotter in CephFS provisioner pod
|
|
||||||
enableCephfsSnapshotter: true
|
|
||||||
# -- Enable Snapshotter in NFS provisioner pod
|
|
||||||
enableNFSSnapshotter: true
|
|
||||||
# -- Enable Snapshotter in RBD provisioner pod
|
|
||||||
enableRBDSnapshotter: true
|
|
||||||
# -- Enable Host mount for `/etc/selinux` directory for Ceph CSI nodeplugins
|
|
||||||
enablePluginSelinuxHostMount: false
|
|
||||||
# -- Enable Ceph CSI PVC encryption support
|
|
||||||
enableCSIEncryption: false
|
|
||||||
|
|
||||||
# -- Enable volume group snapshot feature. This feature is
|
|
||||||
# enabled by default as long as the necessary CRDs are available in the cluster.
|
|
||||||
enableVolumeGroupSnapshot: true
|
|
||||||
# -- PriorityClassName to be set on csi driver plugin pods
|
|
||||||
pluginPriorityClassName: system-node-critical
|
|
||||||
|
|
||||||
# -- PriorityClassName to be set on csi driver provisioner pods
|
|
||||||
provisionerPriorityClassName: system-cluster-critical
|
|
||||||
|
|
||||||
# -- Policy for modifying a volume's ownership or permissions when the RBD PVC is being mounted.
|
|
||||||
# supported values are documented at https://kubernetes-csi.github.io/docs/support-fsgroup.html
|
|
||||||
rbdFSGroupPolicy: "File"
|
|
||||||
|
|
||||||
# -- Policy for modifying a volume's ownership or permissions when the CephFS PVC is being mounted.
|
|
||||||
# supported values are documented at https://kubernetes-csi.github.io/docs/support-fsgroup.html
|
|
||||||
cephFSFSGroupPolicy: "File"
|
|
||||||
|
|
||||||
# -- Policy for modifying a volume's ownership or permissions when the NFS PVC is being mounted.
|
|
||||||
# supported values are documented at https://kubernetes-csi.github.io/docs/support-fsgroup.html
|
|
||||||
nfsFSGroupPolicy: "File"
|
|
||||||
|
|
||||||
# -- OMAP generator generates the omap mapping between the PV name and the RBD image
|
|
||||||
# which helps CSI to identify the rbd images for CSI operations.
|
|
||||||
# `CSI_ENABLE_OMAP_GENERATOR` needs to be enabled when we are using rbd mirroring feature.
|
|
||||||
# By default OMAP generator is disabled and when enabled, it will be deployed as a
|
|
||||||
# sidecar with CSI provisioner pod, to enable set it to true.
|
|
||||||
enableOMAPGenerator: false
|
|
||||||
|
|
||||||
# -- Set CephFS Kernel mount options to use https://docs.ceph.com/en/latest/man/8/mount.ceph/#options.
|
|
||||||
# Set to "ms_mode=secure" when connections.encrypted is enabled in CephCluster CR
|
|
||||||
cephFSKernelMountOptions:
|
|
||||||
|
|
||||||
# -- Enable adding volume metadata on the CephFS subvolumes and RBD images.
|
|
||||||
# Not all users might be interested in getting volume/snapshot details as metadata on CephFS subvolume and RBD images.
|
|
||||||
# Hence enable metadata is false by default
|
|
||||||
enableMetadata: false
|
|
||||||
|
|
||||||
# -- Set replicas for csi provisioner deployment
|
|
||||||
provisionerReplicas: 2
|
|
||||||
|
|
||||||
# -- Cluster name identifier to set as metadata on the CephFS subvolume and RBD images. This will be useful
|
|
||||||
# in cases like for example, when two container orchestrator clusters (Kubernetes/OCP) are using a single ceph cluster
|
|
||||||
clusterName:
|
|
||||||
|
|
||||||
# -- Set logging level for cephCSI containers maintained by the cephCSI.
|
|
||||||
# Supported values from 0 to 5. 0 for general useful logs, 5 for trace level verbosity.
|
|
||||||
logLevel: 0
|
|
||||||
|
|
||||||
# -- Set logging level for Kubernetes-csi sidecar containers.
|
|
||||||
# Supported values from 0 to 5. 0 for general useful logs (the default), 5 for trace level verbosity.
|
|
||||||
# @default -- `0`
|
|
||||||
sidecarLogLevel:
|
|
||||||
|
|
||||||
# -- CSI driver name prefix for cephfs, rbd and nfs.
|
|
||||||
# @default -- `namespace name where rook-ceph operator is deployed`
|
|
||||||
csiDriverNamePrefix:
|
|
||||||
|
|
||||||
# -- CSI RBD plugin daemonset update strategy, supported values are OnDelete and RollingUpdate
|
|
||||||
# @default -- `RollingUpdate`
|
|
||||||
rbdPluginUpdateStrategy:
|
|
||||||
|
|
||||||
# -- A maxUnavailable parameter of CSI RBD plugin daemonset update strategy.
|
|
||||||
# @default -- `1`
|
|
||||||
rbdPluginUpdateStrategyMaxUnavailable:
|
|
||||||
|
|
||||||
# -- CSI CephFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate
|
|
||||||
# @default -- `RollingUpdate`
|
|
||||||
cephFSPluginUpdateStrategy:
|
|
||||||
|
|
||||||
# -- A maxUnavailable parameter of CSI cephFS plugin daemonset update strategy.
|
|
||||||
# @default -- `1`
|
|
||||||
cephFSPluginUpdateStrategyMaxUnavailable:
|
|
||||||
|
|
||||||
# -- CSI NFS plugin daemonset update strategy, supported values are OnDelete and RollingUpdate
|
|
||||||
# @default -- `RollingUpdate`
|
|
||||||
nfsPluginUpdateStrategy:
|
|
||||||
|
|
||||||
# -- Set GRPC timeout for csi containers (in seconds). It should be >= 120. If this value is not set or is invalid, it defaults to 150
|
|
||||||
grpcTimeoutInSeconds: 150
|
|
||||||
|
|
||||||
# -- Burst to use while communicating with the kubernetes apiserver.
|
|
||||||
kubeApiBurst:
|
|
||||||
|
|
||||||
# -- QPS to use while communicating with the kubernetes apiserver.
|
|
||||||
kubeApiQPS:
|
|
||||||
|
|
||||||
# -- The volume of the CephCSI RBD plugin DaemonSet
|
|
||||||
csiRBDPluginVolume:
|
|
||||||
# - name: lib-modules
|
|
||||||
# hostPath:
|
|
||||||
# path: /run/booted-system/kernel-modules/lib/modules/
|
|
||||||
# - name: host-nix
|
|
||||||
# hostPath:
|
|
||||||
# path: /nix
|
|
||||||
|
|
||||||
# -- The volume mounts of the CephCSI RBD plugin DaemonSet
|
|
||||||
csiRBDPluginVolumeMount:
|
|
||||||
# - name: host-nix
|
|
||||||
# mountPath: /nix
|
|
||||||
# readOnly: true
|
|
||||||
|
|
||||||
# -- The volume of the CephCSI CephFS plugin DaemonSet
|
|
||||||
csiCephFSPluginVolume:
|
|
||||||
# - name: lib-modules
|
|
||||||
# hostPath:
|
|
||||||
# path: /run/booted-system/kernel-modules/lib/modules/
|
|
||||||
# - name: host-nix
|
|
||||||
# hostPath:
|
|
||||||
# path: /nix
|
|
||||||
|
|
||||||
# -- The volume mounts of the CephCSI CephFS plugin DaemonSet
|
|
||||||
csiCephFSPluginVolumeMount:
|
|
||||||
# - name: host-nix
|
|
||||||
# mountPath: /nix
|
|
||||||
# readOnly: true
|
|
||||||
|
|
||||||
# -- CEPH CSI RBD provisioner resource requirement list
|
|
||||||
# csi-omap-generator resources will be applied only if `enableOMAPGenerator` is set to `true`
|
|
||||||
# @default -- see values.yaml
|
|
||||||
csiRBDProvisionerResource: |
|
|
||||||
- name : csi-provisioner
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-resizer
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-attacher
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-snapshotter
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-rbdplugin
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
- name : csi-omap-generator
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
- name : liveness-prometheus
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
# -- CEPH CSI RBD plugin resource requirement list
|
|
||||||
# @default -- see values.yaml
|
|
||||||
csiRBDPluginResource: |
|
|
||||||
- name : driver-registrar
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-rbdplugin
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
- name : liveness-prometheus
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
# -- CEPH CSI CephFS provisioner resource requirement list
|
|
||||||
# @default -- see values.yaml
|
|
||||||
csiCephFSProvisionerResource: |
|
|
||||||
- name : csi-provisioner
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-resizer
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-attacher
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-snapshotter
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-cephfsplugin
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
- name : liveness-prometheus
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
# -- CEPH CSI CephFS plugin resource requirement list
|
|
||||||
# @default -- see values.yaml
|
|
||||||
csiCephFSPluginResource: |
|
|
||||||
- name : driver-registrar
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-cephfsplugin
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
- name : liveness-prometheus
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
|
|
||||||
# -- CEPH CSI NFS provisioner resource requirement list
|
|
||||||
# @default -- see values.yaml
|
|
||||||
csiNFSProvisionerResource: |
|
|
||||||
- name : csi-provisioner
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 100m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-nfsplugin
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
- name : csi-attacher
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
|
|
||||||
# -- CEPH CSI NFS plugin resource requirement list
|
|
||||||
# @default -- see values.yaml
|
|
||||||
csiNFSPluginResource: |
|
|
||||||
- name : driver-registrar
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 128Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
- name : csi-nfsplugin
|
|
||||||
resource:
|
|
||||||
requests:
|
|
||||||
memory: 512Mi
|
|
||||||
cpu: 250m
|
|
||||||
limits:
|
|
||||||
memory: 1Gi
|
|
||||||
|
|
||||||
# Set provisionerTolerations and provisionerNodeAffinity for provisioner pod.
|
|
||||||
# The CSI provisioner would be best to start on the same nodes as other ceph daemons.
|
|
||||||
|
|
||||||
# -- Array of tolerations in YAML format which will be added to CSI provisioner deployment
|
|
||||||
provisionerTolerations:
|
|
||||||
# - key: key
|
|
||||||
# operator: Exists
|
|
||||||
# effect: NoSchedule
|
|
||||||
|
|
||||||
# -- The node labels for affinity of the CSI provisioner deployment [^1]
|
|
||||||
provisionerNodeAffinity: #key1=value1,value2; key2=value3
|
|
||||||
# Set pluginTolerations and pluginNodeAffinity for plugin daemonset pods.
|
|
||||||
# The CSI plugins need to be started on all the nodes where the clients need to mount the storage.
|
|
||||||
|
|
||||||
# -- Array of tolerations in YAML format which will be added to CephCSI plugin DaemonSet
|
|
||||||
pluginTolerations:
|
|
||||||
# - key: key
|
|
||||||
# operator: Exists
|
|
||||||
# effect: NoSchedule
|
|
||||||
|
|
||||||
# -- The node labels for affinity of the CephCSI RBD plugin DaemonSet [^1]
|
|
||||||
pluginNodeAffinity: # key1=value1,value2; key2=value3
|
|
||||||
|
|
||||||
# -- Enable Ceph CSI Liveness sidecar deployment
|
|
||||||
enableLiveness: false
|
|
||||||
|
|
||||||
# -- CSI CephFS driver metrics port
|
|
||||||
# @default -- `9081`
|
|
||||||
cephfsLivenessMetricsPort:
|
|
||||||
|
|
||||||
# -- CSI Addons server port
|
|
||||||
# @default -- `9070`
|
|
||||||
csiAddonsPort:
|
|
||||||
# -- CSI Addons server port for the RBD provisioner
|
|
||||||
# @default -- `9070`
|
|
||||||
csiAddonsRBDProvisionerPort:
|
|
||||||
# -- CSI Addons server port for the Ceph FS provisioner
|
|
||||||
# @default -- `9070`
|
|
||||||
csiAddonsCephFSProvisionerPort:
|
|
||||||
|
|
||||||
# -- Enable Ceph Kernel clients on kernel < 4.17. If your kernel does not support quotas for CephFS
|
|
||||||
# you may want to disable this setting. However, this will cause an issue during upgrades
|
|
||||||
# with the FUSE client. See the [upgrade guide](https://rook.io/docs/rook/v1.2/ceph-upgrade.html)
|
|
||||||
forceCephFSKernelClient: true
|
|
||||||
|
|
||||||
# -- Ceph CSI RBD driver metrics port
|
|
||||||
# @default -- `8080`
|
|
||||||
rbdLivenessMetricsPort:
|
|
||||||
|
|
||||||
serviceMonitor:
|
|
||||||
# -- Enable ServiceMonitor for Ceph CSI drivers
|
|
||||||
enabled: false
|
|
||||||
# -- Service monitor scrape interval
|
|
||||||
interval: 10s
|
|
||||||
# -- ServiceMonitor additional labels
|
|
||||||
labels: {}
|
|
||||||
# -- Use a different namespace for the ServiceMonitor
|
|
||||||
namespace:
|
|
||||||
|
|
||||||
# -- Kubelet root directory path (if the Kubelet uses a different path for the `--root-dir` flag)
|
|
||||||
# @default -- `/var/lib/kubelet`
|
|
||||||
kubeletDirPath:
|
|
||||||
|
|
||||||
# -- Duration in seconds that non-leader candidates will wait to force acquire leadership.
|
|
||||||
# @default -- `137s`
|
|
||||||
csiLeaderElectionLeaseDuration:
|
|
||||||
|
|
||||||
# -- Deadline in seconds that the acting leader will retry refreshing leadership before giving up.
|
|
||||||
# @default -- `107s`
|
|
||||||
csiLeaderElectionRenewDeadline:
|
|
||||||
|
|
||||||
# -- Retry period in seconds the LeaderElector clients should wait between tries of actions.
|
|
||||||
# @default -- `26s`
|
|
||||||
csiLeaderElectionRetryPeriod:
|
|
||||||
|
|
||||||
cephcsi:
|
|
||||||
# -- Ceph CSI image repository
|
|
||||||
repository: quay.io/cephcsi/cephcsi
|
|
||||||
# -- Ceph CSI image tag
|
|
||||||
tag: v3.14.0
|
|
||||||
|
|
||||||
registrar:
|
|
||||||
# -- Kubernetes CSI registrar image repository
|
|
||||||
repository: registry.k8s.io/sig-storage/csi-node-driver-registrar
|
|
||||||
# -- Registrar image tag
|
|
||||||
tag: v2.13.0
|
|
||||||
|
|
||||||
provisioner:
|
|
||||||
# -- Kubernetes CSI provisioner image repository
|
|
||||||
repository: registry.k8s.io/sig-storage/csi-provisioner
|
|
||||||
# -- Provisioner image tag
|
|
||||||
tag: v5.1.0
|
|
||||||
|
|
||||||
snapshotter:
|
|
||||||
# -- Kubernetes CSI snapshotter image repository
|
|
||||||
repository: registry.k8s.io/sig-storage/csi-snapshotter
|
|
||||||
# -- Snapshotter image tag
|
|
||||||
tag: v8.2.0
|
|
||||||
|
|
||||||
attacher:
|
|
||||||
# -- Kubernetes CSI Attacher image repository
|
|
||||||
repository: registry.k8s.io/sig-storage/csi-attacher
|
|
||||||
# -- Attacher image tag
|
|
||||||
tag: v4.8.0
|
|
||||||
|
|
||||||
resizer:
|
|
||||||
# -- Kubernetes CSI resizer image repository
|
|
||||||
repository: registry.k8s.io/sig-storage/csi-resizer
|
|
||||||
# -- Resizer image tag
|
|
||||||
tag: v1.13.1
|
|
||||||
|
|
||||||
# -- Image pull policy
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
|
|
||||||
# -- Labels to add to the CSI CephFS Deployments and DaemonSets Pods
|
|
||||||
cephfsPodLabels: #"key1=value1,key2=value2"
|
|
||||||
|
|
||||||
# -- Labels to add to the CSI NFS Deployments and DaemonSets Pods
|
|
||||||
nfsPodLabels: #"key1=value1,key2=value2"
|
|
||||||
|
|
||||||
# -- Labels to add to the CSI RBD Deployments and DaemonSets Pods
|
|
||||||
rbdPodLabels: #"key1=value1,key2=value2"
|
|
||||||
|
|
||||||
csiAddons:
|
|
||||||
# -- Enable CSIAddons
|
|
||||||
enabled: false
|
|
||||||
# -- CSIAddons sidecar image repository
|
|
||||||
repository: quay.io/csiaddons/k8s-sidecar
|
|
||||||
# -- CSIAddons sidecar image tag
|
|
||||||
tag: v0.12.0
|
|
||||||
|
|
||||||
nfs:
|
|
||||||
# -- Enable the nfs csi driver
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
topology:
|
|
||||||
# -- Enable topology based provisioning
|
|
||||||
enabled: false
|
|
||||||
# NOTE: the value here serves as an example and needs to be
|
|
||||||
# updated with node labels that define domains of interest
|
|
||||||
# -- domainLabels define which node labels to use as domains
|
|
||||||
# for CSI nodeplugins to advertise their domains
|
|
||||||
domainLabels:
|
|
||||||
# - kubernetes.io/hostname
|
|
||||||
# - topology.kubernetes.io/zone
|
|
||||||
# - topology.rook.io/rack
|
|
||||||
|
|
||||||
# -- Whether to skip any attach operation altogether for CephFS PVCs. See more details
|
|
||||||
# [here](https://kubernetes-csi.github.io/docs/skip-attach.html#skip-attach-with-csi-driver-object).
|
|
||||||
# If cephFSAttachRequired is set to false it skips the volume attachments and makes the creation
|
|
||||||
# of pods using the CephFS PVC fast. **WARNING** It's highly discouraged to use this for
|
|
||||||
# CephFS RWO volumes. Refer to this [issue](https://github.com/kubernetes/kubernetes/issues/103305) for more details.
|
|
||||||
cephFSAttachRequired: true
|
|
||||||
# -- Whether to skip any attach operation altogether for RBD PVCs. See more details
|
|
||||||
# [here](https://kubernetes-csi.github.io/docs/skip-attach.html#skip-attach-with-csi-driver-object).
|
|
||||||
# If set to false it skips the volume attachments and makes the creation of pods using the RBD PVC fast.
|
|
||||||
# **WARNING** It's highly discouraged to use this for RWO volumes as it can cause data corruption.
|
|
||||||
# csi-addons operations like Reclaimspace and PVC Keyrotation will also not be supported if set
|
|
||||||
# to false since we'll have no VolumeAttachments to determine which node the PVC is mounted on.
|
|
||||||
# Refer to this [issue](https://github.com/kubernetes/kubernetes/issues/103305) for more details.
|
|
||||||
rbdAttachRequired: true
|
|
||||||
# -- Whether to skip any attach operation altogether for NFS PVCs. See more details
|
|
||||||
# [here](https://kubernetes-csi.github.io/docs/skip-attach.html#skip-attach-with-csi-driver-object).
|
|
||||||
# If cephFSAttachRequired is set to false it skips the volume attachments and makes the creation
|
|
||||||
# of pods using the NFS PVC fast. **WARNING** It's highly discouraged to use this for
|
|
||||||
# NFS RWO volumes. Refer to this [issue](https://github.com/kubernetes/kubernetes/issues/103305) for more details.
|
|
||||||
nfsAttachRequired: true
|
|
||||||
|
|
||||||
# -- Enable discovery daemon
|
|
||||||
enableDiscoveryDaemon: false
|
|
||||||
# -- Set the discovery daemon device discovery interval (default to 60m)
|
|
||||||
discoveryDaemonInterval: 60m
|
|
||||||
|
|
||||||
# -- The timeout for ceph commands in seconds
|
|
||||||
cephCommandsTimeoutSeconds: "15"
|
|
||||||
|
|
||||||
# -- If true, run rook operator on the host network
|
|
||||||
useOperatorHostNetwork:
|
|
||||||
|
|
||||||
# -- If true, scale down the rook operator.
|
|
||||||
# This is useful for administrative actions where the rook operator must be scaled down, while using gitops style tooling
|
|
||||||
# to deploy your helm charts.
|
|
||||||
scaleDownOperator: false
|
|
||||||
|
|
||||||
## Rook Discover configuration
|
|
||||||
## toleration: NoSchedule, PreferNoSchedule or NoExecute
|
|
||||||
## tolerationKey: Set this to the specific key of the taint to tolerate
|
|
||||||
## tolerations: Array of tolerations in YAML format which will be added to agent deployment
|
|
||||||
## nodeAffinity: Set to labels of the node to match
|
|
||||||
|
|
||||||
discover:
|
|
||||||
# -- Toleration for the discover pods.
|
|
||||||
# Options: `NoSchedule`, `PreferNoSchedule` or `NoExecute`
|
|
||||||
toleration:
|
|
||||||
# -- The specific key of the taint to tolerate
|
|
||||||
tolerationKey:
|
|
||||||
# -- Array of tolerations in YAML format which will be added to discover deployment
|
|
||||||
tolerations:
|
|
||||||
# - key: key
|
|
||||||
# operator: Exists
|
|
||||||
# effect: NoSchedule
|
|
||||||
# -- The node labels for affinity of `discover-agent` [^1]
|
|
||||||
nodeAffinity:
|
|
||||||
# key1=value1,value2; key2=value3
|
|
||||||
#
|
|
||||||
# or
|
|
||||||
#
|
|
||||||
# requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
# nodeSelectorTerms:
|
|
||||||
# - matchExpressions:
|
|
||||||
# - key: storage-node
|
|
||||||
# operator: Exists
|
|
||||||
# -- Labels to add to the discover pods
|
|
||||||
podLabels: # "key1=value1,key2=value2"
|
|
||||||
# -- Add resources to discover daemon pods
|
|
||||||
resources:
|
|
||||||
# - limits:
|
|
||||||
# memory: 512Mi
|
|
||||||
# - requests:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 128Mi
|
|
||||||
|
|
||||||
# -- Custom label to identify node hostname. If not set `kubernetes.io/hostname` will be used
|
|
||||||
customHostnameLabel:
|
|
||||||
|
|
||||||
# -- Runs Ceph Pods as privileged to be able to write to `hostPaths` in OpenShift with SELinux restrictions.
|
|
||||||
hostpathRequiresPrivileged: false
|
|
||||||
|
|
||||||
# -- Whether to create all Rook pods to run on the host network, for example in environments where a CNI is not enabled
|
|
||||||
enforceHostNetwork: false
|
|
||||||
|
|
||||||
# -- Disable automatic orchestration when new devices are discovered.
|
|
||||||
disableDeviceHotplug: false
|
|
||||||
|
|
||||||
# -- The revision history limit for all pods created by Rook. If blank, the K8s default is 10.
|
|
||||||
revisionHistoryLimit:
|
|
||||||
|
|
||||||
# -- Blacklist certain disks according to the regex provided.
|
|
||||||
discoverDaemonUdev:
|
|
||||||
|
|
||||||
# -- imagePullSecrets option allow to pull docker images from private docker registry. Option will be passed to all service accounts.
|
|
||||||
imagePullSecrets:
|
|
||||||
# - name: my-registry-secret
|
|
||||||
|
|
||||||
# -- Whether the OBC provisioner should watch on the operator namespace or not, if not the namespace of the cluster will be used
|
|
||||||
enableOBCWatchOperatorNamespace: true
|
|
||||||
|
|
||||||
# -- Specify the prefix for the OBC provisioner in place of the cluster namespace
|
|
||||||
# @default -- `ceph cluster namespace`
|
|
||||||
obcProvisionerNamePrefix:
|
|
||||||
|
|
||||||
# -- Many OBC additional config fields may be risky for administrators to allow users control over.
|
|
||||||
# The safe and default-allowed fields are 'maxObjects' and 'maxSize'.
|
|
||||||
# Other fields should be considered risky. To allow all additional configs, use this value:
|
|
||||||
# "maxObjects,maxSize,bucketMaxObjects,bucketMaxSize,bucketPolicy,bucketLifecycle,bucketOwner"
|
|
||||||
# @default -- "maxObjects,maxSize"
|
|
||||||
obcAllowAdditionalConfigFields: "maxObjects,maxSize"
|
|
||||||
|
|
||||||
monitoring:
|
|
||||||
# -- Enable monitoring. Requires Prometheus to be pre-installed.
|
|
||||||
# Enabling will also create RBAC rules to allow Operator to create ServiceMonitors
|
|
||||||
enabled: false
|
|
||||||
@@ -1,145 +1,26 @@
|
|||||||
use std::{
|
|
||||||
net::{IpAddr, Ipv4Addr},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use cidr::Ipv4Cidr;
|
|
||||||
use harmony::{
|
use harmony::{
|
||||||
hardware::{FirewallGroup, HostCategory, Location, PhysicalHost, SwitchGroup},
|
|
||||||
infra::opnsense::OPNSenseManagementInterface,
|
|
||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
maestro::Maestro,
|
maestro::Maestro,
|
||||||
modules::{
|
modules::dummy::{ErrorScore, PanicScore, SuccessScore},
|
||||||
http::HttpScore,
|
topology::HAClusterTopology,
|
||||||
ipxe::IpxeScore,
|
|
||||||
okd::{
|
|
||||||
bootstrap_dhcp::OKDBootstrapDhcpScore,
|
|
||||||
bootstrap_load_balancer::OKDBootstrapLoadBalancerScore, dhcp::OKDDhcpScore,
|
|
||||||
dns::OKDDnsScore,
|
|
||||||
},
|
|
||||||
tftp::TftpScore,
|
|
||||||
},
|
|
||||||
topology::{LogicalHost, UnmanagedRouter, Url},
|
|
||||||
};
|
};
|
||||||
use harmony_macros::{ip, mac_address};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let firewall = harmony::topology::LogicalHost {
|
let inventory = Inventory::autoload();
|
||||||
ip: ip!("192.168.33.1"),
|
let topology = HAClusterTopology::autoload();
|
||||||
name: String::from("fw0"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let opnsense = Arc::new(
|
|
||||||
harmony::infra::opnsense::OPNSenseFirewall::new(firewall, None, "root", "opnsense").await,
|
|
||||||
);
|
|
||||||
let lan_subnet = Ipv4Addr::new(192, 168, 33, 0);
|
|
||||||
let gateway_ipv4 = Ipv4Addr::new(192, 168, 33, 1);
|
|
||||||
let gateway_ip = IpAddr::V4(gateway_ipv4);
|
|
||||||
let topology = harmony::topology::HAClusterTopology {
|
|
||||||
domain_name: "ncd0.harmony.mcd".to_string(), // TODO this must be set manually correctly
|
|
||||||
// when setting up the opnsense firewall
|
|
||||||
router: Arc::new(UnmanagedRouter::new(
|
|
||||||
gateway_ip,
|
|
||||||
Ipv4Cidr::new(lan_subnet, 24).unwrap(),
|
|
||||||
)),
|
|
||||||
load_balancer: opnsense.clone(),
|
|
||||||
firewall: opnsense.clone(),
|
|
||||||
tftp_server: opnsense.clone(),
|
|
||||||
http_server: opnsense.clone(),
|
|
||||||
dhcp_server: opnsense.clone(),
|
|
||||||
dns_server: opnsense.clone(),
|
|
||||||
control_plane: vec![
|
|
||||||
LogicalHost {
|
|
||||||
ip: ip!("192.168.33.20"),
|
|
||||||
name: "cp0".to_string(),
|
|
||||||
},
|
|
||||||
LogicalHost {
|
|
||||||
ip: ip!("192.168.33.21"),
|
|
||||||
name: "cp1".to_string(),
|
|
||||||
},
|
|
||||||
LogicalHost {
|
|
||||||
ip: ip!("192.168.33.22"),
|
|
||||||
name: "cp2".to_string(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
bootstrap_host: LogicalHost {
|
|
||||||
ip: ip!("192.168.33.66"),
|
|
||||||
name: "bootstrap".to_string(),
|
|
||||||
},
|
|
||||||
workers: vec![
|
|
||||||
LogicalHost {
|
|
||||||
ip: ip!("192.168.33.30"),
|
|
||||||
name: "wk0".to_string(),
|
|
||||||
},
|
|
||||||
LogicalHost {
|
|
||||||
ip: ip!("192.168.33.31"),
|
|
||||||
name: "wk1".to_string(),
|
|
||||||
},
|
|
||||||
LogicalHost {
|
|
||||||
ip: ip!("192.168.33.32"),
|
|
||||||
name: "wk2".to_string(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
switch: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
let inventory = Inventory {
|
|
||||||
location: Location::new("I am mobile".to_string(), "earth".to_string()),
|
|
||||||
switch: SwitchGroup::from([]),
|
|
||||||
firewall: FirewallGroup::from([PhysicalHost::empty(HostCategory::Firewall)
|
|
||||||
.management(Arc::new(OPNSenseManagementInterface::new()))]),
|
|
||||||
storage_host: vec![],
|
|
||||||
worker_host: vec![
|
|
||||||
PhysicalHost::empty(HostCategory::Server)
|
|
||||||
.mac_address(mac_address!("C4:62:37:02:61:0F")),
|
|
||||||
PhysicalHost::empty(HostCategory::Server)
|
|
||||||
.mac_address(mac_address!("C4:62:37:02:61:26")),
|
|
||||||
// thisone
|
|
||||||
// Then create the ipxe file
|
|
||||||
// set the dns static leases
|
|
||||||
// bootstrap nodes
|
|
||||||
// start ceph cluster
|
|
||||||
// try installation of lampscore
|
|
||||||
// bingo?
|
|
||||||
PhysicalHost::empty(HostCategory::Server)
|
|
||||||
.mac_address(mac_address!("C4:62:37:02:61:70")),
|
|
||||||
],
|
|
||||||
control_plane_host: vec![
|
|
||||||
PhysicalHost::empty(HostCategory::Server)
|
|
||||||
.mac_address(mac_address!("C4:62:37:02:60:FA")),
|
|
||||||
PhysicalHost::empty(HostCategory::Server)
|
|
||||||
.mac_address(mac_address!("C4:62:37:02:61:1A")),
|
|
||||||
PhysicalHost::empty(HostCategory::Server)
|
|
||||||
.mac_address(mac_address!("C4:62:37:01:BC:68")),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO regroup smaller scores in a larger one such as this
|
|
||||||
// let okd_boostrap_preparation();
|
|
||||||
|
|
||||||
let bootstrap_dhcp_score = OKDBootstrapDhcpScore::new(&topology, &inventory);
|
|
||||||
let bootstrap_load_balancer_score = OKDBootstrapLoadBalancerScore::new(&topology);
|
|
||||||
let dhcp_score = OKDDhcpScore::new(&topology, &inventory);
|
|
||||||
let dns_score = OKDDnsScore::new(&topology);
|
|
||||||
let load_balancer_score =
|
|
||||||
harmony::modules::okd::load_balancer::OKDLoadBalancerScore::new(&topology);
|
|
||||||
|
|
||||||
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
|
|
||||||
let http_score = HttpScore::new(Url::LocalFolder(
|
|
||||||
"./data/watchguard/pxe-http-files".to_string(),
|
|
||||||
));
|
|
||||||
let ipxe_score = IpxeScore::new();
|
|
||||||
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();
|
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();
|
||||||
|
|
||||||
maestro.register_all(vec![
|
maestro.register_all(vec![
|
||||||
Box::new(dns_score),
|
// ADD scores :
|
||||||
Box::new(bootstrap_dhcp_score),
|
// 1. OPNSense setup scores
|
||||||
Box::new(bootstrap_load_balancer_score),
|
// 2. Bootstrap node setup
|
||||||
Box::new(load_balancer_score),
|
// 3. Control plane setup
|
||||||
Box::new(tftp_score),
|
// 4. Workers setup
|
||||||
Box::new(http_score),
|
// 5. Various tools and apps setup
|
||||||
Box::new(ipxe_score),
|
Box::new(SuccessScore {}),
|
||||||
Box::new(dhcp_score),
|
Box::new(ErrorScore {}),
|
||||||
|
Box::new(PanicScore {}),
|
||||||
]);
|
]);
|
||||||
harmony_tui::init(maestro).await.unwrap();
|
harmony_tui::init(maestro).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,23 +13,23 @@ rust-ipmi = "0.1.1"
|
|||||||
semver = "1.0.23"
|
semver = "1.0.23"
|
||||||
serde = { version = "1.0.209", features = ["derive"] }
|
serde = { version = "1.0.209", features = ["derive"] }
|
||||||
serde_json = "1.0.127"
|
serde_json = "1.0.127"
|
||||||
tokio.workspace = true
|
tokio = { workspace = true }
|
||||||
derive-new.workspace = true
|
derive-new = { workspace = true }
|
||||||
log.workspace = true
|
log = { workspace = true }
|
||||||
env_logger.workspace = true
|
env_logger = { workspace = true }
|
||||||
async-trait.workspace = true
|
async-trait = { workspace = true }
|
||||||
cidr.workspace = true
|
cidr = { workspace = true }
|
||||||
opnsense-config = { path = "../opnsense-config" }
|
opnsense-config = { path = "../opnsense-config" }
|
||||||
opnsense-config-xml = { path = "../opnsense-config-xml" }
|
opnsense-config-xml = { path = "../opnsense-config-xml" }
|
||||||
harmony_macros = { path = "../harmony_macros" }
|
harmony_macros = { path = "../harmony_macros" }
|
||||||
harmony_types = { path = "../harmony_types" }
|
harmony_types = { path = "../harmony_types" }
|
||||||
uuid.workspace = true
|
uuid = { workspace = true }
|
||||||
url.workspace = true
|
url = { workspace = true }
|
||||||
kube.workspace = true
|
kube = { workspace = true }
|
||||||
k8s-openapi.workspace = true
|
k8s-openapi = { workspace = true }
|
||||||
serde_yaml.workspace = true
|
serde_yaml = { workspace = true }
|
||||||
http.workspace = true
|
http = { workspace = true }
|
||||||
serde-value.workspace = true
|
serde-value = { workspace = true }
|
||||||
inquire.workspace = true
|
inquire.workspace = true
|
||||||
helm-wrapper-rs = "0.4.0"
|
helm-wrapper-rs = "0.4.0"
|
||||||
non-blank-string-rs = "1.0.4"
|
non-blank-string-rs = "1.0.4"
|
||||||
@@ -38,14 +38,3 @@ directories = "6.0.0"
|
|||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
dockerfile_builder = "0.1.5"
|
dockerfile_builder = "0.1.5"
|
||||||
temp-file = "0.1.9"
|
temp-file = "0.1.9"
|
||||||
convert_case.workspace = true
|
|
||||||
email_address = "0.2.9"
|
|
||||||
fqdn = { version = "0.4.6", features = [
|
|
||||||
"domain-label-cannot-start-or-end-with-hyphen",
|
|
||||||
"domain-label-length-limited-to-63",
|
|
||||||
"domain-name-without-special-chars",
|
|
||||||
"domain-name-length-limited-to-255",
|
|
||||||
"punycode",
|
|
||||||
"serde",
|
|
||||||
] }
|
|
||||||
temp-dir = "0.1.14"
|
|
||||||
|
|||||||
@@ -6,8 +6,4 @@ lazy_static! {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.data_dir()
|
.data_dir()
|
||||||
.join("harmony");
|
.join("harmony");
|
||||||
pub static ref REGISTRY_URL: String =
|
|
||||||
std::env::var("HARMONY_REGISTRY_URL").unwrap_or_else(|_| "hub.nationtech.io".to_string());
|
|
||||||
pub static ref REGISTRY_PROJECT: String =
|
|
||||||
std::env::var("HARMONY_REGISTRY_PROJECT").unwrap_or_else(|_| "harmony".to_string());
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,8 +138,7 @@ impl ManagementInterface for ManualManagementInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_supported_protocol_names(&self) -> String {
|
fn get_supported_protocol_names(&self) -> String {
|
||||||
// todo!()
|
todo!()
|
||||||
"none".to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ pub enum InterpretName {
|
|||||||
LoadBalancer,
|
LoadBalancer,
|
||||||
Tftp,
|
Tftp,
|
||||||
Http,
|
Http,
|
||||||
Ipxe,
|
|
||||||
Dummy,
|
Dummy,
|
||||||
Panic,
|
Panic,
|
||||||
OPNSense,
|
OPNSense,
|
||||||
@@ -30,7 +29,6 @@ impl std::fmt::Display for InterpretName {
|
|||||||
InterpretName::LoadBalancer => f.write_str("LoadBalancer"),
|
InterpretName::LoadBalancer => f.write_str("LoadBalancer"),
|
||||||
InterpretName::Tftp => f.write_str("Tftp"),
|
InterpretName::Tftp => f.write_str("Tftp"),
|
||||||
InterpretName::Http => f.write_str("Http"),
|
InterpretName::Http => f.write_str("Http"),
|
||||||
InterpretName::Ipxe => f.write_str("iPXE"),
|
|
||||||
InterpretName::Dummy => f.write_str("Dummy"),
|
InterpretName::Dummy => f.write_str("Dummy"),
|
||||||
InterpretName::Panic => f.write_str("Panic"),
|
InterpretName::Panic => f.write_str("Panic"),
|
||||||
InterpretName::OPNSense => f.write_str("OPNSense"),
|
InterpretName::OPNSense => f.write_str("OPNSense"),
|
||||||
@@ -41,8 +39,12 @@ impl std::fmt::Display for InterpretName {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Interpret<T>: std::fmt::Debug + Send {
|
pub trait Interpret<T>: std::fmt::Debug + Send {
|
||||||
async fn execute(&self, inventory: &Inventory, topology: &T)
|
async fn execute(
|
||||||
-> Result<Outcome, InterpretError>;
|
&self,
|
||||||
|
inventory: &Inventory,
|
||||||
|
topology: &T,
|
||||||
|
profile: &String,
|
||||||
|
) -> Result<Outcome, InterpretError>;
|
||||||
fn get_name(&self) -> InterpretName;
|
fn get_name(&self) -> InterpretName;
|
||||||
fn get_version(&self) -> Version;
|
fn get_version(&self) -> Version;
|
||||||
fn get_status(&self) -> InterpretStatus;
|
fn get_status(&self) -> InterpretStatus;
|
||||||
|
|||||||
@@ -16,20 +16,23 @@ pub struct Maestro<T: Topology> {
|
|||||||
topology: T,
|
topology: T,
|
||||||
scores: Arc<RwLock<ScoreVec<T>>>,
|
scores: Arc<RwLock<ScoreVec<T>>>,
|
||||||
topology_preparation_result: Mutex<Option<Outcome>>,
|
topology_preparation_result: Mutex<Option<Outcome>>,
|
||||||
|
profile: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology> Maestro<T> {
|
impl<T: Topology> Maestro<T> {
|
||||||
pub fn new(inventory: Inventory, topology: T) -> Self {
|
pub fn new(inventory: Inventory, topology: T, profile: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inventory,
|
inventory,
|
||||||
topology,
|
topology,
|
||||||
scores: Arc::new(RwLock::new(Vec::new())),
|
scores: Arc::new(RwLock::new(Vec::new())),
|
||||||
topology_preparation_result: None.into(),
|
topology_preparation_result: None.into(),
|
||||||
|
profile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn initialize(inventory: Inventory, topology: T) -> Result<Self, InterpretError> {
|
pub async fn initialize(inventory: Inventory, topology: T) -> Result<Self, InterpretError> {
|
||||||
let instance = Self::new(inventory, topology);
|
let profile = "dev".to_string(); // TODO: retrieve from env?
|
||||||
|
let instance = Self::new(inventory, topology, profile);
|
||||||
instance.prepare_topology().await?;
|
instance.prepare_topology().await?;
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
@@ -78,9 +81,11 @@ impl<T: Topology> Maestro<T> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
info!("Running score {score:?}");
|
info!("Running score {score:?}");
|
||||||
let interpret = score.create_interpret();
|
let interpret = score.apply_profile(&self.profile).create_interpret();
|
||||||
info!("Launching interpret {interpret:?}");
|
info!("Launching interpret {interpret:?}");
|
||||||
let result = interpret.execute(&self.inventory, &self.topology).await;
|
let result = interpret
|
||||||
|
.execute(&self.inventory, &self.topology, &self.profile)
|
||||||
|
.await;
|
||||||
info!("Got result {result:?}");
|
info!("Got result {result:?}");
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ use super::{interpret::Interpret, topology::Topology};
|
|||||||
pub trait Score<T: Topology>:
|
pub trait Score<T: Topology>:
|
||||||
std::fmt::Debug + ScoreToString<T> + Send + Sync + CloneBoxScore<T> + SerializeScore<T>
|
std::fmt::Debug + ScoreToString<T> + Send + Sync + CloneBoxScore<T> + SerializeScore<T>
|
||||||
{
|
{
|
||||||
|
fn apply_profile(&self, profile: &String) -> Box<dyn Score<T>> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>>;
|
fn create_interpret(&self) -> Box<dyn Interpret<T>>;
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,16 +168,6 @@ impl DhcpServer for HAClusterTopology {
|
|||||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||||
self.dhcp_server.commit_config().await
|
self.dhcp_server.commit_config().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_filename(filename).await
|
|
||||||
}
|
|
||||||
async fn set_filename64(&self, filename64: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_filename64(filename64).await
|
|
||||||
}
|
|
||||||
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_filenameipxe(filenameipxe).await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -303,15 +293,6 @@ impl DhcpServer for DummyInfra {
|
|||||||
async fn set_boot_filename(&self, _boot_filename: &str) -> Result<(), ExecutorError> {
|
async fn set_boot_filename(&self, _boot_filename: &str) -> Result<(), ExecutorError> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
}
|
}
|
||||||
async fn set_filename(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
async fn set_filename64(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
async fn set_filenameipxe(&self, _filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use k8s_openapi::NamespaceResourceScope;
|
use k8s_openapi::NamespaceResourceScope;
|
||||||
use kube::{
|
use kube::{Api, Client, Error, Resource, api::PostParams};
|
||||||
Api, Client, Config, Error, Resource,
|
|
||||||
api::PostParams,
|
|
||||||
config::{KubeConfigOptions, Kubeconfig},
|
|
||||||
};
|
|
||||||
use log::error;
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
@@ -43,11 +38,7 @@ impl K8sClient {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn apply_namespaced<K>(
|
pub async fn apply_namespaced<K>(&self, resource: &Vec<K>) -> Result<K, Error>
|
||||||
&self,
|
|
||||||
resource: &Vec<K>,
|
|
||||||
ns: Option<&str>,
|
|
||||||
) -> Result<Vec<K>, Error>
|
|
||||||
where
|
where
|
||||||
K: Resource<Scope = NamespaceResourceScope>
|
K: Resource<Scope = NamespaceResourceScope>
|
||||||
+ Clone
|
+ Clone
|
||||||
@@ -57,32 +48,10 @@ impl K8sClient {
|
|||||||
+ Default,
|
+ Default,
|
||||||
<K as kube::Resource>::DynamicType: Default,
|
<K as kube::Resource>::DynamicType: Default,
|
||||||
{
|
{
|
||||||
let mut resources = Vec::new();
|
|
||||||
for r in resource.iter() {
|
for r in resource.iter() {
|
||||||
let api: Api<K> = match ns {
|
let api: Api<K> = Api::default_namespaced(self.client.clone());
|
||||||
Some(ns) => Api::namespaced(self.client.clone(), ns),
|
api.create(&PostParams::default(), &r).await?;
|
||||||
None => Api::default_namespaced(self.client.clone()),
|
|
||||||
};
|
|
||||||
resources.push(api.create(&PostParams::default(), &r).await?);
|
|
||||||
}
|
}
|
||||||
Ok(resources)
|
todo!("")
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn from_kubeconfig(path: &str) -> Option<K8sClient> {
|
|
||||||
let k = match Kubeconfig::read_from(path) {
|
|
||||||
Ok(k) => k,
|
|
||||||
Err(e) => {
|
|
||||||
error!("Failed to load kubeconfig from {path} : {e}");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some(K8sClient::new(
|
|
||||||
Client::try_from(
|
|
||||||
Config::from_custom_kubeconfig(k, &KubeConfigOptions::default())
|
|
||||||
.await
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ use super::{HelmCommand, K8sclient, Topology, k8s::K8sClient};
|
|||||||
|
|
||||||
struct K8sState {
|
struct K8sState {
|
||||||
client: Arc<K8sClient>,
|
client: Arc<K8sClient>,
|
||||||
source: K8sSource,
|
_source: K8sSource,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum K8sSource {
|
enum K8sSource {
|
||||||
LocalK3d,
|
LocalK3d,
|
||||||
Kubeconfig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct K8sAnywhereTopology {
|
pub struct K8sAnywhereTopology {
|
||||||
@@ -76,7 +75,7 @@ impl K8sAnywhereTopology {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn try_load_kubeconfig(&self, path: &str) -> Option<K8sClient> {
|
async fn try_load_kubeconfig(&self, path: &str) -> Option<K8sClient> {
|
||||||
K8sClient::from_kubeconfig(path).await
|
todo!("Use kube-rs to load kubeconfig at path {path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_k3d_installation_score(&self) -> K3DInstallationScore {
|
fn get_k3d_installation_score(&self) -> K3DInstallationScore {
|
||||||
@@ -92,7 +91,9 @@ impl K8sAnywhereTopology {
|
|||||||
|
|
||||||
async fn try_get_or_install_k8s_client(&self) -> Result<Option<K8sState>, InterpretError> {
|
async fn try_get_or_install_k8s_client(&self) -> Result<Option<K8sState>, InterpretError> {
|
||||||
let k8s_anywhere_config = K8sAnywhereConfig {
|
let k8s_anywhere_config = K8sAnywhereConfig {
|
||||||
kubeconfig: std::env::var("KUBECONFIG").ok().map(|v| v.to_string()),
|
kubeconfig: std::env::var("HARMONY_KUBECONFIG")
|
||||||
|
.ok()
|
||||||
|
.map(|v| v.to_string()),
|
||||||
use_system_kubeconfig: std::env::var("HARMONY_USE_SYSTEM_KUBECONFIG")
|
use_system_kubeconfig: std::env::var("HARMONY_USE_SYSTEM_KUBECONFIG")
|
||||||
.map_or_else(|_| false, |v| v.parse().ok().unwrap_or(false)),
|
.map_or_else(|_| false, |v| v.parse().ok().unwrap_or(false)),
|
||||||
autoinstall: std::env::var("HARMONY_AUTOINSTALL")
|
autoinstall: std::env::var("HARMONY_AUTOINSTALL")
|
||||||
@@ -108,18 +109,8 @@ impl K8sAnywhereTopology {
|
|||||||
|
|
||||||
if let Some(kubeconfig) = k8s_anywhere_config.kubeconfig {
|
if let Some(kubeconfig) = k8s_anywhere_config.kubeconfig {
|
||||||
match self.try_load_kubeconfig(&kubeconfig).await {
|
match self.try_load_kubeconfig(&kubeconfig).await {
|
||||||
Some(client) => {
|
Some(_client) => todo!(),
|
||||||
return Ok(Some(K8sState {
|
None => todo!(),
|
||||||
client: Arc::new(client),
|
|
||||||
source: K8sSource::Kubeconfig,
|
|
||||||
message: format!("Loaded k8s client from kubeconfig {kubeconfig}"),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(InterpretError::new(format!(
|
|
||||||
"Failed to load kubeconfig from {kubeconfig}"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +142,7 @@ impl K8sAnywhereTopology {
|
|||||||
let state = match k3d.get_client().await {
|
let state = match k3d.get_client().await {
|
||||||
Ok(client) => K8sState {
|
Ok(client) => K8sState {
|
||||||
client: Arc::new(K8sClient::new(client)),
|
client: Arc::new(K8sClient::new(client)),
|
||||||
source: K8sSource::LocalK3d,
|
_source: K8sSource::LocalK3d,
|
||||||
message: "Successfully installed K3D cluster and acquired client".to_string(),
|
message: "Successfully installed K3D cluster and acquired client".to_string(),
|
||||||
},
|
},
|
||||||
Err(_) => todo!(),
|
Err(_) => todo!(),
|
||||||
|
|||||||
@@ -53,9 +53,6 @@ pub trait DhcpServer: Send + Sync + std::fmt::Debug {
|
|||||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>;
|
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>;
|
||||||
async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError>;
|
async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError>;
|
||||||
async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError>;
|
async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError>;
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError>;
|
|
||||||
async fn set_filename64(&self, filename64: &str) -> Result<(), ExecutorError>;
|
|
||||||
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError>;
|
|
||||||
fn get_ip(&self) -> IpAddress;
|
fn get_ip(&self) -> IpAddress;
|
||||||
fn get_host(&self) -> LogicalHost;
|
fn get_host(&self) -> LogicalHost;
|
||||||
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
||||||
|
|||||||
@@ -69,34 +69,4 @@ impl DhcpServer for OPNSenseFirewall {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filename(filename);
|
|
||||||
debug!("OPNsense dhcp server set filename {filename}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_filename64(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filename64(filename);
|
|
||||||
debug!("OPNsense dhcp server set filename {filename}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filenameipxe(filenameipxe);
|
|
||||||
debug!("OPNsense dhcp server set filenameipxe {filenameipxe}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ impl HttpServer for OPNSenseFirewall {
|
|||||||
info!("Adding custom caddy config files");
|
info!("Adding custom caddy config files");
|
||||||
config
|
config
|
||||||
.upload_files(
|
.upload_files(
|
||||||
"./data/watchguard/caddy_config",
|
"../../../watchguard/caddy_config",
|
||||||
"/usr/local/etc/caddy/caddy.d/",
|
"/usr/local/etc/caddy/caddy.d/",
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -370,13 +370,10 @@ mod tests {
|
|||||||
let result = get_servers_for_backend(&backend, &haproxy);
|
let result = get_servers_for_backend(&backend, &haproxy);
|
||||||
|
|
||||||
// Check the result
|
// Check the result
|
||||||
assert_eq!(
|
assert_eq!(result, vec![BackendServer {
|
||||||
result,
|
address: "192.168.1.1".to_string(),
|
||||||
vec![BackendServer {
|
port: 80,
|
||||||
address: "192.168.1.1".to_string(),
|
},]);
|
||||||
port: 80,
|
|
||||||
},]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_servers_for_backend_no_linked_servers() {
|
fn test_get_servers_for_backend_no_linked_servers() {
|
||||||
@@ -433,18 +430,15 @@ mod tests {
|
|||||||
// Call the function
|
// Call the function
|
||||||
let result = get_servers_for_backend(&backend, &haproxy);
|
let result = get_servers_for_backend(&backend, &haproxy);
|
||||||
// Check the result
|
// Check the result
|
||||||
assert_eq!(
|
assert_eq!(result, vec![
|
||||||
result,
|
BackendServer {
|
||||||
vec![
|
address: "some-hostname.test.mcd".to_string(),
|
||||||
BackendServer {
|
port: 80,
|
||||||
address: "some-hostname.test.mcd".to_string(),
|
},
|
||||||
port: 80,
|
BackendServer {
|
||||||
},
|
address: "192.168.1.2".to_string(),
|
||||||
BackendServer {
|
port: 8080,
|
||||||
address: "192.168.1.2".to_string(),
|
},
|
||||||
port: 8080,
|
]);
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
use std::{collections::HashMap, str::FromStr};
|
|
||||||
|
|
||||||
use non_blank_string_rs::NonBlankString;
|
|
||||||
use serde::Serialize;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
modules::helm::chart::{HelmChartScore, HelmRepository},
|
|
||||||
score::Score,
|
|
||||||
topology::{HelmCommand, Topology},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Clone)]
|
|
||||||
pub struct CertManagerHelmScore {}
|
|
||||||
|
|
||||||
impl<T: Topology + HelmCommand> Score<T> for CertManagerHelmScore {
|
|
||||||
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
|
|
||||||
let mut values_overrides = HashMap::new();
|
|
||||||
values_overrides.insert(
|
|
||||||
NonBlankString::from_str("crds.enabled").unwrap(),
|
|
||||||
"true".to_string(),
|
|
||||||
);
|
|
||||||
let values_overrides = Some(values_overrides);
|
|
||||||
|
|
||||||
HelmChartScore {
|
|
||||||
namespace: Some(NonBlankString::from_str("cert-manager").unwrap()),
|
|
||||||
release_name: NonBlankString::from_str("cert-manager").unwrap(),
|
|
||||||
chart_name: NonBlankString::from_str("jetstack/cert-manager").unwrap(),
|
|
||||||
chart_version: None,
|
|
||||||
values_overrides,
|
|
||||||
values_yaml: None,
|
|
||||||
create_namespace: true,
|
|
||||||
install_only: true,
|
|
||||||
repository: Some(HelmRepository::new(
|
|
||||||
"jetstack".to_string(),
|
|
||||||
Url::parse("https://charts.jetstack.io").unwrap(),
|
|
||||||
true,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
.create_interpret()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("CertManagerHelmScore")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
mod helm;
|
|
||||||
pub use helm::*;
|
|
||||||
@@ -17,9 +17,6 @@ pub struct DhcpScore {
|
|||||||
pub host_binding: Vec<HostBinding>,
|
pub host_binding: Vec<HostBinding>,
|
||||||
pub next_server: Option<IpAddress>,
|
pub next_server: Option<IpAddress>,
|
||||||
pub boot_filename: Option<String>,
|
pub boot_filename: Option<String>,
|
||||||
pub filename: Option<String>,
|
|
||||||
pub filename64: Option<String>,
|
|
||||||
pub filenameipxe: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology + DhcpServer> Score<T> for DhcpScore {
|
impl<T: Topology + DhcpServer> Score<T> for DhcpScore {
|
||||||
@@ -120,44 +117,8 @@ impl DhcpInterpret {
|
|||||||
None => Outcome::noop(),
|
None => Outcome::noop(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let filename_outcome = match &self.score.filename {
|
|
||||||
Some(filename) => {
|
|
||||||
dhcp_server.set_filename(&filename).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filename to {filename}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let filename64_outcome = match &self.score.filename64 {
|
|
||||||
Some(filename64) => {
|
|
||||||
dhcp_server.set_filename64(&filename64).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filename64 to {filename64}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let filenameipxe_outcome = match &self.score.filenameipxe {
|
|
||||||
Some(filenameipxe) => {
|
|
||||||
dhcp_server.set_filenameipxe(&filenameipxe).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filenameipxe to {filenameipxe}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if next_server_outcome.status == InterpretStatus::NOOP
|
if next_server_outcome.status == InterpretStatus::NOOP
|
||||||
&& boot_filename_outcome.status == InterpretStatus::NOOP
|
&& boot_filename_outcome.status == InterpretStatus::NOOP
|
||||||
&& filename_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& filename64_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& filenameipxe_outcome.status == InterpretStatus::NOOP
|
|
||||||
{
|
{
|
||||||
return Ok(Outcome::noop());
|
return Ok(Outcome::noop());
|
||||||
}
|
}
|
||||||
@@ -165,12 +126,8 @@ impl DhcpInterpret {
|
|||||||
Ok(Outcome::new(
|
Ok(Outcome::new(
|
||||||
InterpretStatus::SUCCESS,
|
InterpretStatus::SUCCESS,
|
||||||
format!(
|
format!(
|
||||||
"Dhcp Interpret Set next boot to [{:?}], boot_filename to [{:?}], filename to [{:?}], filename64 to [{:?}], filenameipxe to [:{:?}]",
|
"Dhcp Interpret Set next boot to {:?} and boot_filename to {:?}",
|
||||||
self.score.boot_filename,
|
self.score.boot_filename, self.score.boot_filename
|
||||||
self.score.boot_filename,
|
|
||||||
self.score.filename,
|
|
||||||
self.score.filename64,
|
|
||||||
self.score.filenameipxe
|
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ impl<T: Topology> Interpret<T> for DummyInterpret {
|
|||||||
&self,
|
&self,
|
||||||
_inventory: &Inventory,
|
_inventory: &Inventory,
|
||||||
_topology: &T,
|
_topology: &T,
|
||||||
|
_profile: &String,
|
||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
self.result.clone()
|
self.result.clone()
|
||||||
}
|
}
|
||||||
@@ -121,6 +122,7 @@ impl<T: Topology> Interpret<T> for PanicInterpret {
|
|||||||
&self,
|
&self,
|
||||||
_inventory: &Inventory,
|
_inventory: &Inventory,
|
||||||
_topology: &T,
|
_topology: &T,
|
||||||
|
_profile: &String,
|
||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
panic!("Panic interpret always panics when executed")
|
panic!("Panic interpret always panics when executed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,31 +6,11 @@ use crate::topology::{HelmCommand, Topology};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use helm_wrapper_rs;
|
use helm_wrapper_rs;
|
||||||
use helm_wrapper_rs::blocking::{DefaultHelmExecutor, HelmExecutor};
|
use helm_wrapper_rs::blocking::{DefaultHelmExecutor, HelmExecutor};
|
||||||
use log::{debug, info, warn};
|
|
||||||
pub use non_blank_string_rs::NonBlankString;
|
pub use non_blank_string_rs::NonBlankString;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, Output, Stdio};
|
|
||||||
use std::str::FromStr;
|
|
||||||
use temp_file::TempFile;
|
use temp_file::TempFile;
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct HelmRepository {
|
|
||||||
name: String,
|
|
||||||
url: Url,
|
|
||||||
force_update: bool,
|
|
||||||
}
|
|
||||||
impl HelmRepository {
|
|
||||||
pub(crate) fn new(name: String, url: Url, force_update: bool) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
url,
|
|
||||||
force_update,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct HelmChartScore {
|
pub struct HelmChartScore {
|
||||||
@@ -40,11 +20,6 @@ pub struct HelmChartScore {
|
|||||||
pub chart_version: Option<NonBlankString>,
|
pub chart_version: Option<NonBlankString>,
|
||||||
pub values_overrides: Option<HashMap<NonBlankString, String>>,
|
pub values_overrides: Option<HashMap<NonBlankString, String>>,
|
||||||
pub values_yaml: Option<String>,
|
pub values_yaml: Option<String>,
|
||||||
pub create_namespace: bool,
|
|
||||||
|
|
||||||
/// Wether to run `helm upgrade --install` under the hood or only install when not present
|
|
||||||
pub install_only: bool,
|
|
||||||
pub repository: Option<HelmRepository>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology + HelmCommand> Score<T> for HelmChartScore {
|
impl<T: Topology + HelmCommand> Score<T> for HelmChartScore {
|
||||||
@@ -63,78 +38,6 @@ impl<T: Topology + HelmCommand> Score<T> for HelmChartScore {
|
|||||||
pub struct HelmChartInterpret {
|
pub struct HelmChartInterpret {
|
||||||
pub score: HelmChartScore,
|
pub score: HelmChartScore,
|
||||||
}
|
}
|
||||||
impl HelmChartInterpret {
|
|
||||||
fn add_repo(&self) -> Result<(), InterpretError> {
|
|
||||||
let repo = match &self.score.repository {
|
|
||||||
Some(repo) => repo,
|
|
||||||
None => {
|
|
||||||
info!("No Helm repository specified in the score. Skipping repository setup.");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
info!(
|
|
||||||
"Ensuring Helm repository exists: Name='{}', URL='{}', ForceUpdate={}",
|
|
||||||
repo.name, repo.url, repo.force_update
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut add_args = vec!["repo", "add", &repo.name, repo.url.as_str()];
|
|
||||||
if repo.force_update {
|
|
||||||
add_args.push("--force-update");
|
|
||||||
}
|
|
||||||
|
|
||||||
let add_output = run_helm_command(&add_args)?;
|
|
||||||
let full_output = format!(
|
|
||||||
"{}\n{}",
|
|
||||||
String::from_utf8_lossy(&add_output.stdout),
|
|
||||||
String::from_utf8_lossy(&add_output.stderr)
|
|
||||||
);
|
|
||||||
|
|
||||||
match add_output.status.success() {
|
|
||||||
true => {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
return Err(InterpretError::new(format!(
|
|
||||||
"Failed to add helm repository!\n{full_output}"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_helm_command(args: &[&str]) -> Result<Output, InterpretError> {
|
|
||||||
let command_str = format!("helm {}", args.join(" "));
|
|
||||||
debug!("Got KUBECONFIG: `{}`", std::env::var("KUBECONFIG").unwrap());
|
|
||||||
debug!("Running Helm command: `{}`", command_str);
|
|
||||||
|
|
||||||
let output = Command::new("helm")
|
|
||||||
.args(args)
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::piped())
|
|
||||||
.output()
|
|
||||||
.map_err(|e| {
|
|
||||||
InterpretError::new(format!(
|
|
||||||
"Failed to execute helm command '{}': {}. Is helm installed and in PATH?",
|
|
||||||
command_str, e
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
||||||
warn!(
|
|
||||||
"Helm command `{}` failed with status: {}\nStdout:\n{}\nStderr:\n{}",
|
|
||||||
command_str, output.status, stdout, stderr
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
debug!(
|
|
||||||
"Helm command `{}` finished successfully. Status: {}",
|
|
||||||
command_str, output.status
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret {
|
impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret {
|
||||||
@@ -158,56 +61,7 @@ impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.add_repo()?;
|
let helm_executor = DefaultHelmExecutor::new();
|
||||||
|
|
||||||
let helm_executor = DefaultHelmExecutor::new_with_opts(
|
|
||||||
&NonBlankString::from_str("helm").unwrap(),
|
|
||||||
None,
|
|
||||||
900,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut helm_options = Vec::new();
|
|
||||||
if self.score.create_namespace {
|
|
||||||
helm_options.push(NonBlankString::from_str("--create-namespace").unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.score.install_only {
|
|
||||||
let chart_list = match helm_executor.list(Some(ns)) {
|
|
||||||
Ok(charts) => charts,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(InterpretError::new(format!(
|
|
||||||
"Failed to list scores in namespace {:?} because of error : {}",
|
|
||||||
self.score.namespace, e
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if chart_list
|
|
||||||
.iter()
|
|
||||||
.any(|item| item.name == self.score.release_name.to_string())
|
|
||||||
{
|
|
||||||
info!(
|
|
||||||
"Release '{}' already exists in namespace '{}'. Skipping installation as install_only is true.",
|
|
||||||
self.score.release_name, ns
|
|
||||||
);
|
|
||||||
|
|
||||||
return Ok(Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!(
|
|
||||||
"Helm Chart '{}' already installed to namespace {ns} and install_only=true",
|
|
||||||
self.score.release_name
|
|
||||||
),
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
info!(
|
|
||||||
"Release '{}' not found in namespace '{}'. Proceeding with installation.",
|
|
||||||
self.score.release_name, ns
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = helm_executor.install_or_upgrade(
|
let res = helm_executor.install_or_upgrade(
|
||||||
&ns,
|
&ns,
|
||||||
&self.score.release_name,
|
&self.score.release_name,
|
||||||
@@ -215,7 +69,7 @@ impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret {
|
|||||||
self.score.chart_version.as_ref(),
|
self.score.chart_version.as_ref(),
|
||||||
self.score.values_overrides.as_ref(),
|
self.score.values_overrides.as_ref(),
|
||||||
yaml_path,
|
yaml_path,
|
||||||
Some(&helm_options),
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let status = match res {
|
let status = match res {
|
||||||
|
|||||||
@@ -1,379 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
use log::debug;
|
|
||||||
use non_blank_string_rs::NonBlankString;
|
|
||||||
use serde::Serialize;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::env::temp_dir;
|
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::process::{Command, Output};
|
|
||||||
use temp_dir::{self, TempDir};
|
|
||||||
use temp_file::TempFile;
|
|
||||||
|
|
||||||
use crate::data::{Id, Version};
|
|
||||||
use crate::interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome};
|
|
||||||
use crate::inventory::Inventory;
|
|
||||||
use crate::score::Score;
|
|
||||||
use crate::topology::{HelmCommand, K8sclient, Topology};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct HelmCommandExecutor {
|
|
||||||
pub env: HashMap<String, String>,
|
|
||||||
pub path: Option<PathBuf>,
|
|
||||||
pub args: Vec<String>,
|
|
||||||
pub api_versions: Option<Vec<String>>,
|
|
||||||
pub kube_version: String,
|
|
||||||
pub debug: Option<bool>,
|
|
||||||
pub globals: HelmGlobals,
|
|
||||||
pub chart: HelmChart,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct HelmGlobals {
|
|
||||||
pub chart_home: Option<PathBuf>,
|
|
||||||
pub config_home: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct HelmChart {
|
|
||||||
pub name: String,
|
|
||||||
pub version: Option<String>,
|
|
||||||
pub repo: Option<String>,
|
|
||||||
pub release_name: Option<String>,
|
|
||||||
pub namespace: Option<String>,
|
|
||||||
pub additional_values_files: Vec<PathBuf>,
|
|
||||||
pub values_file: Option<PathBuf>,
|
|
||||||
pub values_inline: Option<String>,
|
|
||||||
pub include_crds: Option<bool>,
|
|
||||||
pub skip_hooks: Option<bool>,
|
|
||||||
pub api_versions: Option<Vec<String>>,
|
|
||||||
pub kube_version: Option<String>,
|
|
||||||
pub name_template: String,
|
|
||||||
pub skip_tests: Option<bool>,
|
|
||||||
pub debug: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HelmCommandExecutor {
|
|
||||||
pub fn generate(mut self) -> Result<String, std::io::Error> {
|
|
||||||
if self.globals.chart_home.is_none() {
|
|
||||||
self.globals.chart_home = Some(PathBuf::from("charts"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if self
|
|
||||||
.clone()
|
|
||||||
.chart
|
|
||||||
.clone()
|
|
||||||
.chart_exists_locally(self.clone().globals.chart_home.unwrap())
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
if self.chart.repo.is_none() {
|
|
||||||
return Err(std::io::Error::new(
|
|
||||||
ErrorKind::Other,
|
|
||||||
"Chart doesn't exist locally and no repo specified",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
self.clone().run_command(
|
|
||||||
self.chart
|
|
||||||
.clone()
|
|
||||||
.pull_command(self.globals.chart_home.clone().unwrap()),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let out = match self.clone().run_command(
|
|
||||||
self.chart
|
|
||||||
.clone()
|
|
||||||
.helm_args(self.globals.chart_home.clone().unwrap()),
|
|
||||||
) {
|
|
||||||
Ok(out) => out,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: don't use unwrap here
|
|
||||||
let s = String::from_utf8(out.stdout).unwrap();
|
|
||||||
debug!("helm stderr: {}", String::from_utf8(out.stderr).unwrap());
|
|
||||||
debug!("helm status: {}", out.status);
|
|
||||||
debug!("helm output: {s}");
|
|
||||||
|
|
||||||
let clean = s.split_once("---").unwrap().1;
|
|
||||||
|
|
||||||
Ok(clean.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn version(self) -> Result<String, std::io::Error> {
|
|
||||||
let out = match self.run_command(vec![
|
|
||||||
"version".to_string(),
|
|
||||||
"-c".to_string(),
|
|
||||||
"--short".to_string(),
|
|
||||||
]) {
|
|
||||||
Ok(out) => out,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: don't use unwrap
|
|
||||||
Ok(String::from_utf8(out.stdout).unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_command(mut self, mut args: Vec<String>) -> Result<Output, std::io::Error> {
|
|
||||||
if let Some(d) = self.debug {
|
|
||||||
if d {
|
|
||||||
args.push("--debug".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let path = if let Some(p) = self.path {
|
|
||||||
p
|
|
||||||
} else {
|
|
||||||
PathBuf::from("helm")
|
|
||||||
};
|
|
||||||
|
|
||||||
let config_home = match self.globals.config_home {
|
|
||||||
Some(p) => p,
|
|
||||||
None => PathBuf::from(TempDir::new()?.path()),
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.chart.values_inline {
|
|
||||||
Some(yaml_str) => {
|
|
||||||
let tf: TempFile;
|
|
||||||
tf = temp_file::with_contents(yaml_str.as_bytes());
|
|
||||||
self.chart
|
|
||||||
.additional_values_files
|
|
||||||
.push(PathBuf::from(tf.path()));
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.env.insert(
|
|
||||||
"HELM_CONFIG_HOME".to_string(),
|
|
||||||
config_home.to_str().unwrap().to_string(),
|
|
||||||
);
|
|
||||||
self.env.insert(
|
|
||||||
"HELM_CACHE_HOME".to_string(),
|
|
||||||
config_home.to_str().unwrap().to_string(),
|
|
||||||
);
|
|
||||||
self.env.insert(
|
|
||||||
"HELM_DATA_HOME".to_string(),
|
|
||||||
config_home.to_str().unwrap().to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Command::new(path).envs(self.env).args(args).output()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HelmChart {
|
|
||||||
pub fn chart_exists_locally(self, chart_home: PathBuf) -> Option<PathBuf> {
|
|
||||||
let chart_path =
|
|
||||||
PathBuf::from(chart_home.to_str().unwrap().to_string() + "/" + &self.name.to_string());
|
|
||||||
|
|
||||||
if chart_path.exists() {
|
|
||||||
Some(chart_path)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pull_command(self, chart_home: PathBuf) -> Vec<String> {
|
|
||||||
let mut args = vec![
|
|
||||||
"pull".to_string(),
|
|
||||||
"--untar".to_string(),
|
|
||||||
"--untardir".to_string(),
|
|
||||||
chart_home.to_str().unwrap().to_string(),
|
|
||||||
];
|
|
||||||
|
|
||||||
match self.repo {
|
|
||||||
Some(r) => {
|
|
||||||
if r.starts_with("oci://") {
|
|
||||||
args.push(String::from(
|
|
||||||
r.trim_end_matches("/").to_string() + "/" + self.name.clone().as_str(),
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
args.push("--repo".to_string());
|
|
||||||
args.push(r.to_string());
|
|
||||||
|
|
||||||
args.push(self.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => args.push(self.name),
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.version {
|
|
||||||
Some(v) => {
|
|
||||||
args.push("--version".to_string());
|
|
||||||
args.push(v.to_string());
|
|
||||||
}
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
args
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn helm_args(self, chart_home: PathBuf) -> Vec<String> {
|
|
||||||
let mut args: Vec<String> = vec!["template".to_string()];
|
|
||||||
|
|
||||||
match self.release_name {
|
|
||||||
Some(rn) => args.push(rn.to_string()),
|
|
||||||
None => args.push("--generate-name".to_string()),
|
|
||||||
}
|
|
||||||
|
|
||||||
args.push(
|
|
||||||
PathBuf::from(chart_home.to_str().unwrap().to_string() + "/" + self.name.as_str())
|
|
||||||
.to_str()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(n) = self.namespace {
|
|
||||||
args.push("--namespace".to_string());
|
|
||||||
args.push(n.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(f) = self.values_file {
|
|
||||||
args.push("-f".to_string());
|
|
||||||
args.push(f.to_str().unwrap().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
for f in self.additional_values_files {
|
|
||||||
args.push("-f".to_string());
|
|
||||||
args.push(f.to_str().unwrap().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(vv) = self.api_versions {
|
|
||||||
for v in vv {
|
|
||||||
args.push("--api-versions".to_string());
|
|
||||||
args.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(kv) = self.kube_version {
|
|
||||||
args.push("--kube-version".to_string());
|
|
||||||
args.push(kv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(crd) = self.include_crds {
|
|
||||||
if crd {
|
|
||||||
args.push("--include-crds".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(st) = self.skip_tests {
|
|
||||||
if st {
|
|
||||||
args.push("--skip-tests".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(sh) = self.skip_hooks {
|
|
||||||
if sh {
|
|
||||||
args.push("--no-hooks".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(d) = self.debug {
|
|
||||||
if d {
|
|
||||||
args.push("--debug".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct HelmChartScoreV2 {
|
|
||||||
pub chart: HelmChart,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Topology + K8sclient + HelmCommand> Score<T> for HelmChartScoreV2 {
|
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
|
||||||
Box::new(HelmChartInterpretV2 {
|
|
||||||
score: self.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!(
|
|
||||||
"{} {} HelmChartScoreV2",
|
|
||||||
self.chart
|
|
||||||
.release_name
|
|
||||||
.clone()
|
|
||||||
.unwrap_or("Unknown".to_string()),
|
|
||||||
self.chart.name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub struct HelmChartInterpretV2 {
|
|
||||||
pub score: HelmChartScoreV2,
|
|
||||||
}
|
|
||||||
impl HelmChartInterpretV2 {}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T: Topology + K8sclient + HelmCommand> Interpret<T> for HelmChartInterpretV2 {
|
|
||||||
async fn execute(
|
|
||||||
&self,
|
|
||||||
_inventory: &Inventory,
|
|
||||||
_topology: &T,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
let ns = self
|
|
||||||
.score
|
|
||||||
.chart
|
|
||||||
.namespace
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or_else(|| todo!("Get namespace from active kubernetes cluster"));
|
|
||||||
|
|
||||||
let helm_executor = HelmCommandExecutor {
|
|
||||||
env: HashMap::new(),
|
|
||||||
path: None,
|
|
||||||
args: vec![],
|
|
||||||
api_versions: None,
|
|
||||||
kube_version: "v1.33.0".to_string(),
|
|
||||||
debug: Some(false),
|
|
||||||
globals: HelmGlobals {
|
|
||||||
chart_home: None,
|
|
||||||
config_home: None,
|
|
||||||
},
|
|
||||||
chart: self.score.chart.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// let mut helm_options = Vec::new();
|
|
||||||
// if self.score.create_namespace {
|
|
||||||
// helm_options.push(NonBlankString::from_str("--create-namespace").unwrap());
|
|
||||||
// }
|
|
||||||
|
|
||||||
let res = helm_executor.generate();
|
|
||||||
|
|
||||||
let output = match res {
|
|
||||||
Ok(output) => output,
|
|
||||||
Err(err) => return Err(InterpretError::new(err.to_string())),
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: implement actually applying the YAML from the templating in the generate function to a k8s cluster, having trouble passing in straight YAML into the k8s client
|
|
||||||
|
|
||||||
// let k8s_resource = k8s_openapi::serde_json::from_str(output.as_str()).unwrap();
|
|
||||||
|
|
||||||
// let client = topology
|
|
||||||
// .k8s_client()
|
|
||||||
// .await
|
|
||||||
// .expect("Environment should provide enough information to instanciate a client")
|
|
||||||
// .apply_namespaced(&vec![output], Some(ns.to_string().as_str()));
|
|
||||||
// match client.apply_yaml(output) {
|
|
||||||
// Ok(_) => return Ok(Outcome::success("Helm chart deployed".to_string())),
|
|
||||||
// Err(e) => return Err(InterpretError::new(e)),
|
|
||||||
// }
|
|
||||||
|
|
||||||
Ok(Outcome::success("Helm chart deployed".to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self) -> InterpretName {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn get_version(&self) -> Version {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn get_status(&self) -> InterpretStatus {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn get_children(&self) -> Vec<Id> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
pub mod chart;
|
pub mod chart;
|
||||||
pub mod command;
|
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
use derive_new::new;
|
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
data::{Id, Version},
|
|
||||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
|
||||||
inventory::Inventory,
|
|
||||||
score::Score,
|
|
||||||
topology::Topology,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, new, Clone, Serialize)]
|
|
||||||
pub struct IpxeScore {
|
|
||||||
//files_to_serve: Url,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Topology> Score<T> for IpxeScore {
|
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
|
||||||
Box::new(IpxeInterpret::new(self.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
"IpxeScore".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, new, Clone)]
|
|
||||||
pub struct IpxeInterpret {
|
|
||||||
_score: IpxeScore,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T: Topology> Interpret<T> for IpxeInterpret {
|
|
||||||
async fn execute(
|
|
||||||
&self,
|
|
||||||
_inventory: &Inventory,
|
|
||||||
_topology: &T,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
/*
|
|
||||||
let http_server = &topology.http_server;
|
|
||||||
http_server.ensure_initialized().await?;
|
|
||||||
Ok(Outcome::success(format!(
|
|
||||||
"Http Server running and serving files from {}",
|
|
||||||
self.score.files_to_serve
|
|
||||||
)))
|
|
||||||
*/
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self) -> InterpretName {
|
|
||||||
InterpretName::Ipxe
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_version(&self) -> Version {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_status(&self) -> InterpretStatus {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_children(&self) -> Vec<Id> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,13 +14,11 @@ use super::resource::{K8sResourceInterpret, K8sResourceScore};
|
|||||||
pub struct K8sDeploymentScore {
|
pub struct K8sDeploymentScore {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub image: String,
|
pub image: String,
|
||||||
pub namespace: Option<String>,
|
|
||||||
pub env_vars: serde_json::Value,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology + K8sclient> Score<T> for K8sDeploymentScore {
|
impl<T: Topology + K8sclient> Score<T> for K8sDeploymentScore {
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||||
let deployment = json!(
|
let deployment: Deployment = serde_json::from_value(json!(
|
||||||
{
|
{
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"name": self.name
|
"name": self.name
|
||||||
@@ -40,21 +38,18 @@ impl<T: Topology + K8sclient> Score<T> for K8sDeploymentScore {
|
|||||||
"spec": {
|
"spec": {
|
||||||
"containers": [
|
"containers": [
|
||||||
{
|
{
|
||||||
"image": self.image,
|
"image": self.image,
|
||||||
"name": self.name,
|
"name": self.image
|
||||||
"imagePullPolicy": "Always",
|
|
||||||
"env": self.env_vars,
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
))
|
||||||
|
.unwrap();
|
||||||
let deployment: Deployment = serde_json::from_value(deployment).unwrap();
|
|
||||||
Box::new(K8sResourceInterpret {
|
Box::new(K8sResourceInterpret {
|
||||||
score: K8sResourceScore::single(deployment.clone(), self.namespace.clone()),
|
score: K8sResourceScore::single(deployment.clone()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
use harmony_macros::ingress_path;
|
|
||||||
use k8s_openapi::api::networking::v1::Ingress;
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
interpret::Interpret,
|
|
||||||
score::Score,
|
|
||||||
topology::{K8sclient, Topology},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::resource::{K8sResourceInterpret, K8sResourceScore};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub enum PathType {
|
|
||||||
ImplementationSpecific,
|
|
||||||
Exact,
|
|
||||||
Prefix,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PathType {
|
|
||||||
fn as_str(&self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
PathType::ImplementationSpecific => "ImplementationSpecific",
|
|
||||||
PathType::Exact => "Exact",
|
|
||||||
PathType::Prefix => "Prefix",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type IngressPath = String;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct K8sIngressScore {
|
|
||||||
pub name: fqdn::FQDN,
|
|
||||||
pub host: fqdn::FQDN,
|
|
||||||
pub backend_service: fqdn::FQDN,
|
|
||||||
pub port: u16,
|
|
||||||
pub path: Option<IngressPath>,
|
|
||||||
pub path_type: Option<PathType>,
|
|
||||||
pub namespace: Option<fqdn::FQDN>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Topology + K8sclient> Score<T> for K8sIngressScore {
|
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
|
||||||
let path = match self.path.clone() {
|
|
||||||
Some(p) => p,
|
|
||||||
None => ingress_path!("/"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let path_type = match self.path_type.clone() {
|
|
||||||
Some(p) => p,
|
|
||||||
None => PathType::Prefix,
|
|
||||||
};
|
|
||||||
|
|
||||||
let ingress = json!(
|
|
||||||
{
|
|
||||||
"metadata": {
|
|
||||||
"name": self.name
|
|
||||||
},
|
|
||||||
"spec": {
|
|
||||||
"rules": [
|
|
||||||
{ "host": self.host,
|
|
||||||
"http": {
|
|
||||||
"paths": [
|
|
||||||
{
|
|
||||||
"path": path,
|
|
||||||
"pathType": path_type.as_str(),
|
|
||||||
"backend": [
|
|
||||||
{
|
|
||||||
"service": self.backend_service,
|
|
||||||
"port": self.port
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let ingress: Ingress = serde_json::from_value(ingress).unwrap();
|
|
||||||
Box::new(K8sResourceInterpret {
|
|
||||||
score: K8sResourceScore::single(
|
|
||||||
ingress.clone(),
|
|
||||||
self.namespace
|
|
||||||
.clone()
|
|
||||||
.map(|f| f.as_c_str().to_str().unwrap().to_string()),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("{} K8sIngressScore", self.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,2 @@
|
|||||||
pub mod deployment;
|
pub mod deployment;
|
||||||
pub mod ingress;
|
|
||||||
pub mod namespace;
|
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
use k8s_openapi::api::core::v1::Namespace;
|
|
||||||
use non_blank_string_rs::NonBlankString;
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
interpret::Interpret,
|
|
||||||
score::Score,
|
|
||||||
topology::{K8sclient, Topology},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct K8sNamespaceScore {
|
|
||||||
pub name: Option<NonBlankString>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Topology + K8sclient> Score<T> for K8sNamespaceScore {
|
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
|
||||||
let name = match &self.name {
|
|
||||||
Some(name) => name,
|
|
||||||
None => todo!(
|
|
||||||
"Return NoOp interpret when no namespace specified or something that makes sense"
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let _namespace: Namespace = serde_json::from_value(json!(
|
|
||||||
{
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "Namespace",
|
|
||||||
"metadata": {
|
|
||||||
"name": name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
todo!(
|
|
||||||
"We currently only support namespaced ressources (see Scope = NamespaceResourceScope)"
|
|
||||||
);
|
|
||||||
// Box::new(K8sResourceInterpret {
|
|
||||||
// score: K8sResourceScore::single(namespace.clone()),
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
"K8sNamespaceScore".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,14 +14,12 @@ use crate::{
|
|||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct K8sResourceScore<K: Resource + std::fmt::Debug> {
|
pub struct K8sResourceScore<K: Resource + std::fmt::Debug> {
|
||||||
pub resource: Vec<K>,
|
pub resource: Vec<K>,
|
||||||
pub namespace: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Resource + std::fmt::Debug> K8sResourceScore<K> {
|
impl<K: Resource + std::fmt::Debug> K8sResourceScore<K> {
|
||||||
pub fn single(resource: K, namespace: Option<String>) -> Self {
|
pub fn single(resource: K) -> Self {
|
||||||
Self {
|
Self {
|
||||||
resource: vec![resource],
|
resource: vec![resource],
|
||||||
namespace,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +77,7 @@ where
|
|||||||
.k8s_client()
|
.k8s_client()
|
||||||
.await
|
.await
|
||||||
.expect("Environment should provide enough information to instanciate a client")
|
.expect("Environment should provide enough information to instanciate a client")
|
||||||
.apply_namespaced(&self.score.resource, self.score.namespace.as_deref())
|
.apply_namespaced(&self.score.resource)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(Outcome::success(
|
Ok(Outcome::success(
|
||||||
|
|||||||
@@ -1,22 +1,11 @@
|
|||||||
use convert_case::{Case, Casing};
|
|
||||||
use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, WORKDIR};
|
|
||||||
use dockerfile_builder::{Dockerfile, instruction_builder::EnvBuilder};
|
|
||||||
use fqdn::fqdn;
|
|
||||||
use harmony_macros::ingress_path;
|
|
||||||
use non_blank_string_rs::NonBlankString;
|
|
||||||
use serde_json::json;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fmt::Debug;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use log::{debug, info};
|
use log::info;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::config::{REGISTRY_PROJECT, REGISTRY_URL};
|
|
||||||
use crate::modules::k8s::ingress::K8sIngressScore;
|
|
||||||
use crate::topology::HelmCommand;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{Id, Version},
|
data::{Id, Version},
|
||||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||||
@@ -26,22 +15,24 @@ use crate::{
|
|||||||
topology::{K8sclient, Topology, Url},
|
topology::{K8sclient, Topology, Url},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::helm::chart::HelmChartScore;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct LAMPScore {
|
pub struct LAMPScore {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub domain: Url,
|
pub domain: Url,
|
||||||
pub config: LAMPConfig,
|
pub config: LAMPConfig,
|
||||||
pub php_version: Version,
|
pub php_version: Version,
|
||||||
|
pub profiles: HashMap<&'static str, LAMPProfile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct LAMPConfig {
|
pub struct LAMPConfig {
|
||||||
pub project_root: PathBuf,
|
pub project_root: PathBuf,
|
||||||
pub ssl_enabled: bool,
|
pub ssl_enabled: bool,
|
||||||
pub database_size: Option<String>,
|
}
|
||||||
pub namespace: String,
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct LAMPProfile {
|
||||||
|
pub ssl_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LAMPConfig {
|
impl Default for LAMPConfig {
|
||||||
@@ -49,13 +40,28 @@ impl Default for LAMPConfig {
|
|||||||
LAMPConfig {
|
LAMPConfig {
|
||||||
project_root: Path::new("./src").to_path_buf(),
|
project_root: Path::new("./src").to_path_buf(),
|
||||||
ssl_enabled: true,
|
ssl_enabled: true,
|
||||||
database_size: None,
|
|
||||||
namespace: "harmony-lamp".to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology + K8sclient + HelmCommand> Score<T> for LAMPScore {
|
impl<T: Topology + K8sclient> Score<T> for LAMPScore {
|
||||||
|
fn apply_profile(&self, profile: &String) -> Box<dyn Score<T>> {
|
||||||
|
let profile = match self.profiles.get(profile.as_str()) {
|
||||||
|
Some(profile) => profile,
|
||||||
|
None => panic!("Not good"), // TODO: better handling
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = LAMPConfig {
|
||||||
|
ssl_enabled: profile.ssl_enabled,
|
||||||
|
..self.config.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
Box::new(LAMPScore {
|
||||||
|
config,
|
||||||
|
..self.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||||
Box::new(LAMPInterpret {
|
Box::new(LAMPInterpret {
|
||||||
score: self.clone(),
|
score: self.clone(),
|
||||||
@@ -73,11 +79,12 @@ pub struct LAMPInterpret {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T: Topology + K8sclient + HelmCommand> Interpret<T> for LAMPInterpret {
|
impl<T: Topology + K8sclient> Interpret<T> for LAMPInterpret {
|
||||||
async fn execute(
|
async fn execute(
|
||||||
&self,
|
&self,
|
||||||
inventory: &Inventory,
|
inventory: &Inventory,
|
||||||
topology: &T,
|
topology: &T,
|
||||||
|
profile: &String,
|
||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
let image_name = match self.build_docker_image() {
|
let image_name = match self.build_docker_image() {
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
@@ -89,78 +96,19 @@ impl<T: Topology + K8sclient + HelmCommand> Interpret<T> for LAMPInterpret {
|
|||||||
};
|
};
|
||||||
info!("LAMP docker image built {image_name}");
|
info!("LAMP docker image built {image_name}");
|
||||||
|
|
||||||
let remote_name = match self.push_docker_image(&image_name) {
|
|
||||||
Ok(remote_name) => remote_name,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(InterpretError::new(format!(
|
|
||||||
"Could not push docker image {e}"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
info!("LAMP docker image pushed to {remote_name}");
|
|
||||||
|
|
||||||
info!("Deploying database");
|
|
||||||
self.deploy_database(inventory, topology).await?;
|
|
||||||
|
|
||||||
let base_name = self.score.name.to_case(Case::Kebab);
|
|
||||||
let secret_name = format!("{}-database-mariadb", base_name);
|
|
||||||
|
|
||||||
let deployment_score = K8sDeploymentScore {
|
let deployment_score = K8sDeploymentScore {
|
||||||
name: <LAMPScore as Score<T>>::name(&self.score).to_case(Case::Kebab),
|
name: <LAMPScore as Score<T>>::name(&self.score),
|
||||||
image: remote_name,
|
image: image_name,
|
||||||
namespace: self.get_namespace().map(|nbs| nbs.to_string()),
|
|
||||||
env_vars: json!([
|
|
||||||
{
|
|
||||||
"name": "MYSQL_PASSWORD",
|
|
||||||
"valueFrom": {
|
|
||||||
"secretKeyRef": {
|
|
||||||
"name": secret_name,
|
|
||||||
"key": "mariadb-root-password"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "MYSQL_HOST",
|
|
||||||
"value": secret_name
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Deploying score {deployment_score:#?}");
|
|
||||||
|
|
||||||
deployment_score
|
|
||||||
.create_interpret()
|
|
||||||
.execute(inventory, topology)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
info!("LAMP deployment_score {deployment_score:?}");
|
info!("LAMP deployment_score {deployment_score:?}");
|
||||||
|
todo!();
|
||||||
let lamp_ingress = K8sIngressScore {
|
deployment_score
|
||||||
name: fqdn!("lamp-ingress"),
|
.apply_profile(profile)
|
||||||
host: fqdn!("test"),
|
|
||||||
backend_service: fqdn!(
|
|
||||||
<LAMPScore as Score<T>>::name(&self.score)
|
|
||||||
.to_case(Case::Kebab)
|
|
||||||
.as_str()
|
|
||||||
),
|
|
||||||
port: 8080,
|
|
||||||
path: Some(ingress_path!("/")),
|
|
||||||
path_type: None,
|
|
||||||
namespace: self
|
|
||||||
.get_namespace()
|
|
||||||
.map(|nbs| fqdn!(nbs.to_string().as_str())),
|
|
||||||
};
|
|
||||||
|
|
||||||
lamp_ingress
|
|
||||||
.create_interpret()
|
.create_interpret()
|
||||||
.execute(inventory, topology)
|
.execute(inventory, topology, profile)
|
||||||
.await?;
|
.await?;
|
||||||
|
todo!()
|
||||||
info!("LAMP lamp_ingress {lamp_ingress:?}");
|
|
||||||
|
|
||||||
Ok(Outcome::success(
|
|
||||||
"Successfully deployed LAMP Stack!".to_string(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_name(&self) -> InterpretName {
|
fn get_name(&self) -> InterpretName {
|
||||||
@@ -180,42 +128,15 @@ impl<T: Topology + K8sclient + HelmCommand> Interpret<T> for LAMPInterpret {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LAMPInterpret {
|
use dockerfile_builder::instruction::{CMD, COPY, ENV, EXPOSE, FROM, RUN, WORKDIR};
|
||||||
async fn deploy_database<T: Topology + K8sclient + HelmCommand>(
|
use dockerfile_builder::{Dockerfile, instruction_builder::EnvBuilder};
|
||||||
&self,
|
use std::fs;
|
||||||
inventory: &Inventory,
|
|
||||||
topology: &T,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
let mut values_overrides = HashMap::new();
|
|
||||||
if let Some(database_size) = self.score.config.database_size.clone() {
|
|
||||||
values_overrides.insert(
|
|
||||||
NonBlankString::from_str("primary.persistence.size").unwrap(),
|
|
||||||
database_size,
|
|
||||||
);
|
|
||||||
values_overrides.insert(
|
|
||||||
NonBlankString::from_str("auth.rootPassword").unwrap(),
|
|
||||||
"mariadb-changethis".to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let score = HelmChartScore {
|
|
||||||
namespace: self.get_namespace(),
|
|
||||||
release_name: NonBlankString::from_str(&format!("{}-database", self.score.name))
|
|
||||||
.unwrap(),
|
|
||||||
chart_name: NonBlankString::from_str(
|
|
||||||
"oci://registry-1.docker.io/bitnamicharts/mariadb",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
chart_version: None,
|
|
||||||
values_overrides: Some(values_overrides),
|
|
||||||
create_namespace: true,
|
|
||||||
install_only: false,
|
|
||||||
values_yaml: None,
|
|
||||||
repository: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
score.create_interpret().execute(inventory, topology).await
|
impl LAMPInterpret {
|
||||||
}
|
pub fn build_dockerfile(
|
||||||
fn build_dockerfile(&self, score: &LAMPScore) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
&self,
|
||||||
|
score: &LAMPScore,
|
||||||
|
) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
||||||
let mut dockerfile = Dockerfile::new();
|
let mut dockerfile = Dockerfile::new();
|
||||||
|
|
||||||
// Use the PHP version from the score to determine the base image
|
// Use the PHP version from the score to determine the base image
|
||||||
@@ -263,9 +184,6 @@ impl LAMPInterpret {
|
|||||||
opcache",
|
opcache",
|
||||||
));
|
));
|
||||||
|
|
||||||
dockerfile.push(RUN::from(r#"sed -i 's/VirtualHost \*:80/VirtualHost *:8080/' /etc/apache2/sites-available/000-default.conf && \
|
|
||||||
sed -i 's/^Listen 80$/Listen 8080/' /etc/apache2/ports.conf"#));
|
|
||||||
|
|
||||||
// Copy PHP configuration
|
// Copy PHP configuration
|
||||||
dockerfile.push(RUN::from("mkdir -p /usr/local/etc/php/conf.d/"));
|
dockerfile.push(RUN::from("mkdir -p /usr/local/etc/php/conf.d/"));
|
||||||
|
|
||||||
@@ -305,13 +223,6 @@ opcache.fast_shutdown=1
|
|||||||
sed -i 's/ServerSignature On/ServerSignature Off/' /etc/apache2/conf-enabled/security.conf"
|
sed -i 's/ServerSignature On/ServerSignature Off/' /etc/apache2/conf-enabled/security.conf"
|
||||||
));
|
));
|
||||||
|
|
||||||
// Set env vars
|
|
||||||
dockerfile.push(RUN::from(
|
|
||||||
"echo 'PassEnv MYSQL_PASSWORD' >> /etc/apache2/sites-available/000-default.conf \
|
|
||||||
&& echo 'PassEnv MYSQL_USER' >> /etc/apache2/sites-available/000-default.conf \
|
|
||||||
&& echo 'PassEnv MYSQL_HOST' >> /etc/apache2/sites-available/000-default.conf",
|
|
||||||
));
|
|
||||||
|
|
||||||
// Create a dedicated user for running Apache
|
// Create a dedicated user for running Apache
|
||||||
dockerfile.push(RUN::from(
|
dockerfile.push(RUN::from(
|
||||||
"groupadd -g 1000 appuser && \
|
"groupadd -g 1000 appuser && \
|
||||||
@@ -331,7 +242,7 @@ opcache.fast_shutdown=1
|
|||||||
dockerfile.push(RUN::from("chown -R appuser:appuser /var/www/html"));
|
dockerfile.push(RUN::from("chown -R appuser:appuser /var/www/html"));
|
||||||
|
|
||||||
// Expose Apache port
|
// Expose Apache port
|
||||||
dockerfile.push(EXPOSE::from("8080/tcp"));
|
dockerfile.push(EXPOSE::from("80/tcp"));
|
||||||
|
|
||||||
// Set the default command
|
// Set the default command
|
||||||
dockerfile.push(CMD::from("apache2-foreground"));
|
dockerfile.push(CMD::from("apache2-foreground"));
|
||||||
@@ -343,43 +254,6 @@ opcache.fast_shutdown=1
|
|||||||
Ok(dockerfile_path)
|
Ok(dockerfile_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_output(
|
|
||||||
&self,
|
|
||||||
output: &std::process::Output,
|
|
||||||
msg: &str,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
if !output.status.success() {
|
|
||||||
return Err(format!("{msg}: {}", String::from_utf8_lossy(&output.stderr)).into());
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_docker_image(&self, image_name: &str) -> Result<String, Box<dyn std::error::Error>> {
|
|
||||||
let full_tag = format!("{}/{}/{}", *REGISTRY_URL, *REGISTRY_PROJECT, &image_name);
|
|
||||||
let output = std::process::Command::new("docker")
|
|
||||||
.args(["tag", image_name, &full_tag])
|
|
||||||
.output()?;
|
|
||||||
self.check_output(&output, "Tagging docker image failed")?;
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"docker tag output {} {}",
|
|
||||||
String::from_utf8_lossy(&output.stdout),
|
|
||||||
String::from_utf8_lossy(&output.stderr)
|
|
||||||
);
|
|
||||||
|
|
||||||
let output = std::process::Command::new("docker")
|
|
||||||
.args(["push", &full_tag])
|
|
||||||
.output()?;
|
|
||||||
self.check_output(&output, "Pushing docker image failed")?;
|
|
||||||
debug!(
|
|
||||||
"docker push output {} {}",
|
|
||||||
String::from_utf8_lossy(&output.stdout),
|
|
||||||
String::from_utf8_lossy(&output.stderr)
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(full_tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_docker_image(&self) -> Result<String, Box<dyn std::error::Error>> {
|
pub fn build_docker_image(&self) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
info!("Generating Dockerfile");
|
info!("Generating Dockerfile");
|
||||||
let dockerfile = self.build_dockerfile(&self.score)?;
|
let dockerfile = self.build_dockerfile(&self.score)?;
|
||||||
@@ -413,8 +287,4 @@ opcache.fast_shutdown=1
|
|||||||
|
|
||||||
Ok(image_name)
|
Ok(image_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_namespace(&self) -> Option<NonBlankString> {
|
|
||||||
Some(NonBlankString::from_str(&self.score.config.namespace).unwrap())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
pub mod cert_manager;
|
|
||||||
pub mod dhcp;
|
pub mod dhcp;
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
pub mod dummy;
|
pub mod dummy;
|
||||||
pub mod helm;
|
pub mod helm;
|
||||||
pub mod http;
|
pub mod http;
|
||||||
pub mod ipxe;
|
|
||||||
pub mod k3d;
|
pub mod k3d;
|
||||||
pub mod k8s;
|
pub mod k8s;
|
||||||
pub mod lamp;
|
pub mod lamp;
|
||||||
pub mod load_balancer;
|
pub mod load_balancer;
|
||||||
pub mod monitoring;
|
|
||||||
pub mod okd;
|
pub mod okd;
|
||||||
pub mod opnsense;
|
pub mod opnsense;
|
||||||
pub mod tftp;
|
pub mod tftp;
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
use super::monitoring_alerting::AlertChannel;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct KubePrometheusConfig {
|
|
||||||
pub namespace: String,
|
|
||||||
pub default_rules: bool,
|
|
||||||
pub windows_monitoring: bool,
|
|
||||||
pub alert_manager: bool,
|
|
||||||
pub node_exporter: bool,
|
|
||||||
pub prometheus: bool,
|
|
||||||
pub grafana: bool,
|
|
||||||
pub kubernetes_service_monitors: bool,
|
|
||||||
pub kubernetes_api_server: bool,
|
|
||||||
pub kubelet: bool,
|
|
||||||
pub kube_controller_manager: bool,
|
|
||||||
pub core_dns: bool,
|
|
||||||
pub kube_etcd: bool,
|
|
||||||
pub kube_scheduler: bool,
|
|
||||||
pub kube_proxy: bool,
|
|
||||||
pub kube_state_metrics: bool,
|
|
||||||
pub prometheus_operator: bool,
|
|
||||||
pub alert_channel: Vec<AlertChannel>,
|
|
||||||
}
|
|
||||||
impl KubePrometheusConfig {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
namespace: "monitoring".into(),
|
|
||||||
default_rules: true,
|
|
||||||
windows_monitoring: false,
|
|
||||||
alert_manager: true,
|
|
||||||
alert_channel: Vec::new(),
|
|
||||||
grafana: true,
|
|
||||||
node_exporter: false,
|
|
||||||
prometheus: true,
|
|
||||||
kubernetes_service_monitors: true,
|
|
||||||
kubernetes_api_server: false,
|
|
||||||
kubelet: false,
|
|
||||||
kube_controller_manager: false,
|
|
||||||
kube_etcd: false,
|
|
||||||
kube_proxy: false,
|
|
||||||
kube_state_metrics: true,
|
|
||||||
prometheus_operator: true,
|
|
||||||
core_dns: false,
|
|
||||||
kube_scheduler: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use non_blank_string_rs::NonBlankString;
|
|
||||||
|
|
||||||
use crate::modules::helm::chart::HelmChartScore;
|
|
||||||
|
|
||||||
use super::{config::KubePrometheusConfig, monitoring_alerting::AlertChannel};
|
|
||||||
|
|
||||||
fn get_discord_alert_manager_score(config: &KubePrometheusConfig) -> Option<HelmChartScore> {
|
|
||||||
let (url, name) = config.alert_channel.iter().find_map(|channel| {
|
|
||||||
if let AlertChannel::Discord { webhook_url, name } = channel {
|
|
||||||
Some((webhook_url, name))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let values = format!(
|
|
||||||
r#"
|
|
||||||
environment:
|
|
||||||
- name: "DISCORD_WEBHOOK"
|
|
||||||
value: "{url}"
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
|
|
||||||
Some(HelmChartScore {
|
|
||||||
namespace: Some(NonBlankString::from_str(&config.namespace).unwrap()),
|
|
||||||
release_name: NonBlankString::from_str(&name).unwrap(),
|
|
||||||
chart_name: NonBlankString::from_str("oci://hub.nationtech.io/library/alertmanager-discord")
|
|
||||||
.unwrap(),
|
|
||||||
chart_version: None,
|
|
||||||
values_overrides: None,
|
|
||||||
values_yaml: Some(values.to_string()),
|
|
||||||
create_namespace: true,
|
|
||||||
install_only: true,
|
|
||||||
repository: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn discord_alert_manager_score(config: &KubePrometheusConfig) -> HelmChartScore {
|
|
||||||
if let Some(chart) = get_discord_alert_manager_score(config) {
|
|
||||||
chart
|
|
||||||
} else {
|
|
||||||
panic!("Expected discord alert manager helm chart");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
use super::{config::KubePrometheusConfig, monitoring_alerting::AlertChannel};
|
|
||||||
use log::info;
|
|
||||||
use non_blank_string_rs::NonBlankString;
|
|
||||||
use std::{collections::HashMap, str::FromStr};
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::modules::helm::chart::HelmChartScore;
|
|
||||||
|
|
||||||
pub fn kube_prometheus_helm_chart_score(config: &KubePrometheusConfig) -> HelmChartScore {
|
|
||||||
//TODO this should be make into a rule with default formatting that can be easily passed as a vec
|
|
||||||
//to the overrides or something leaving the user to deal with formatting here seems bad
|
|
||||||
let default_rules = config.default_rules.to_string();
|
|
||||||
let windows_monitoring = config.windows_monitoring.to_string();
|
|
||||||
let alert_manager = config.alert_manager.to_string();
|
|
||||||
let grafana = config.grafana.to_string();
|
|
||||||
let kubernetes_service_monitors = config.kubernetes_service_monitors.to_string();
|
|
||||||
let kubernetes_api_server = config.kubernetes_api_server.to_string();
|
|
||||||
let kubelet = config.kubelet.to_string();
|
|
||||||
let kube_controller_manager = config.kube_controller_manager.to_string();
|
|
||||||
let core_dns = config.core_dns.to_string();
|
|
||||||
let kube_etcd = config.kube_etcd.to_string();
|
|
||||||
let kube_scheduler = config.kube_scheduler.to_string();
|
|
||||||
let kube_proxy = config.kube_proxy.to_string();
|
|
||||||
let kube_state_metrics = config.kube_state_metrics.to_string();
|
|
||||||
let node_exporter = config.node_exporter.to_string();
|
|
||||||
let prometheus_operator = config.prometheus_operator.to_string();
|
|
||||||
let prometheus = config.prometheus.to_string();
|
|
||||||
let mut values = format!(
|
|
||||||
r#"
|
|
||||||
additionalPrometheusRulesMap:
|
|
||||||
pods-status-alerts:
|
|
||||||
groups:
|
|
||||||
- name: pods
|
|
||||||
rules:
|
|
||||||
- alert: "[CRIT] POD not healthy"
|
|
||||||
expr: min_over_time(sum by (namespace, pod) (kube_pod_status_phase{{phase=~"Pending|Unknown|Failed"}})[15m:1m]) > 0
|
|
||||||
for: 0m
|
|
||||||
labels:
|
|
||||||
severity: critical
|
|
||||||
annotations:
|
|
||||||
title: "[CRIT] POD not healthy : {{{{ $labels.pod }}}}"
|
|
||||||
description: |
|
|
||||||
A POD is in a non-ready state!
|
|
||||||
- **Pod**: {{{{ $labels.pod }}}}
|
|
||||||
- **Namespace**: {{{{ $labels.namespace }}}}
|
|
||||||
- alert: "[CRIT] POD crash looping"
|
|
||||||
expr: increase(kube_pod_container_status_restarts_total[5m]) > 3
|
|
||||||
for: 0m
|
|
||||||
labels:
|
|
||||||
severity: critical
|
|
||||||
annotations:
|
|
||||||
title: "[CRIT] POD crash looping : {{{{ $labels.pod }}}}"
|
|
||||||
description: |
|
|
||||||
A POD is drowning in a crash loop!
|
|
||||||
- **Pod**: {{{{ $labels.pod }}}}
|
|
||||||
- **Namespace**: {{{{ $labels.namespace }}}}
|
|
||||||
- **Instance**: {{{{ $labels.instance }}}}
|
|
||||||
pvc-alerts:
|
|
||||||
groups:
|
|
||||||
- name: pvc-alerts
|
|
||||||
rules:
|
|
||||||
- alert: 'PVC Fill Over 95 Percent In 2 Days'
|
|
||||||
expr: |
|
|
||||||
(
|
|
||||||
kubelet_volume_stats_used_bytes
|
|
||||||
/
|
|
||||||
kubelet_volume_stats_capacity_bytes
|
|
||||||
) > 0.95
|
|
||||||
AND
|
|
||||||
predict_linear(kubelet_volume_stats_used_bytes[2d], 2 * 24 * 60 * 60)
|
|
||||||
/
|
|
||||||
kubelet_volume_stats_capacity_bytes
|
|
||||||
> 0.95
|
|
||||||
for: 1m
|
|
||||||
labels:
|
|
||||||
severity: warning
|
|
||||||
annotations:
|
|
||||||
description: The PVC {{{{ $labels.persistentvolumeclaim }}}} in namespace {{{{ $labels.namespace }}}} is predicted to fill over 95% in less than 2 days.
|
|
||||||
title: PVC {{{{ $labels.persistentvolumeclaim }}}} in namespace {{{{ $labels.namespace }}}} will fill over 95% in less than 2 days
|
|
||||||
defaultRules:
|
|
||||||
create: {default_rules}
|
|
||||||
rules:
|
|
||||||
alertmanager: true
|
|
||||||
etcd: true
|
|
||||||
configReloaders: true
|
|
||||||
general: true
|
|
||||||
k8sContainerCpuUsageSecondsTotal: true
|
|
||||||
k8sContainerMemoryCache: true
|
|
||||||
k8sContainerMemoryRss: true
|
|
||||||
k8sContainerMemorySwap: true
|
|
||||||
k8sContainerResource: true
|
|
||||||
k8sContainerMemoryWorkingSetBytes: true
|
|
||||||
k8sPodOwner: true
|
|
||||||
kubeApiserverAvailability: true
|
|
||||||
kubeApiserverBurnrate: true
|
|
||||||
kubeApiserverHistogram: true
|
|
||||||
kubeApiserverSlos: true
|
|
||||||
kubeControllerManager: true
|
|
||||||
kubelet: true
|
|
||||||
kubeProxy: true
|
|
||||||
kubePrometheusGeneral: true
|
|
||||||
kubePrometheusNodeRecording: true
|
|
||||||
kubernetesApps: true
|
|
||||||
kubernetesResources: true
|
|
||||||
kubernetesStorage: true
|
|
||||||
kubernetesSystem: true
|
|
||||||
kubeSchedulerAlerting: true
|
|
||||||
kubeSchedulerRecording: true
|
|
||||||
kubeStateMetrics: true
|
|
||||||
network: true
|
|
||||||
node: true
|
|
||||||
nodeExporterAlerting: true
|
|
||||||
nodeExporterRecording: true
|
|
||||||
prometheus: true
|
|
||||||
prometheusOperator: true
|
|
||||||
windows: true
|
|
||||||
windowsMonitoring:
|
|
||||||
enabled: {windows_monitoring}
|
|
||||||
grafana:
|
|
||||||
enabled: {grafana}
|
|
||||||
kubernetesServiceMonitors:
|
|
||||||
enabled: {kubernetes_service_monitors}
|
|
||||||
kubeApiServer:
|
|
||||||
enabled: {kubernetes_api_server}
|
|
||||||
kubelet:
|
|
||||||
enabled: {kubelet}
|
|
||||||
kubeControllerManager:
|
|
||||||
enabled: {kube_controller_manager}
|
|
||||||
coreDns:
|
|
||||||
enabled: {core_dns}
|
|
||||||
kubeEtcd:
|
|
||||||
enabled: {kube_etcd}
|
|
||||||
kubeScheduler:
|
|
||||||
enabled: {kube_scheduler}
|
|
||||||
kubeProxy:
|
|
||||||
enabled: {kube_proxy}
|
|
||||||
kubeStateMetrics:
|
|
||||||
enabled: {kube_state_metrics}
|
|
||||||
nodeExporter:
|
|
||||||
enabled: {node_exporter}
|
|
||||||
prometheusOperator:
|
|
||||||
enabled: {prometheus_operator}
|
|
||||||
prometheus:
|
|
||||||
enabled: {prometheus}
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
|
|
||||||
let alertmanager_config = alert_manager_yaml_builder(&config);
|
|
||||||
values.push_str(&alertmanager_config);
|
|
||||||
|
|
||||||
fn alert_manager_yaml_builder(config: &KubePrometheusConfig) -> String {
|
|
||||||
let mut receivers = String::new();
|
|
||||||
let mut routes = String::new();
|
|
||||||
let mut global_configs = String::new();
|
|
||||||
let alert_manager = config.alert_manager;
|
|
||||||
for alert_channel in &config.alert_channel {
|
|
||||||
match alert_channel {
|
|
||||||
AlertChannel::Discord { name, .. } => {
|
|
||||||
let (receiver, route) = discord_alert_builder(name);
|
|
||||||
info!("discord receiver: {} \nroute: {}", receiver, route);
|
|
||||||
receivers.push_str(&receiver);
|
|
||||||
routes.push_str(&route);
|
|
||||||
}
|
|
||||||
AlertChannel::Slack {
|
|
||||||
slack_channel,
|
|
||||||
webhook_url,
|
|
||||||
} => {
|
|
||||||
let (receiver, route) = slack_alert_builder(slack_channel);
|
|
||||||
info!("slack receiver: {} \nroute: {}", receiver, route);
|
|
||||||
receivers.push_str(&receiver);
|
|
||||||
|
|
||||||
routes.push_str(&route);
|
|
||||||
let global_config = format!(
|
|
||||||
r#"
|
|
||||||
global:
|
|
||||||
slack_api_url: {webhook_url}"#
|
|
||||||
);
|
|
||||||
|
|
||||||
global_configs.push_str(&global_config);
|
|
||||||
}
|
|
||||||
AlertChannel::Smpt { .. } => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info!("after alert receiver: {}", receivers);
|
|
||||||
info!("after alert routes: {}", routes);
|
|
||||||
|
|
||||||
let alertmanager_config = format!(
|
|
||||||
r#"
|
|
||||||
alertmanager:
|
|
||||||
enabled: {alert_manager}
|
|
||||||
config: {global_configs}
|
|
||||||
route:
|
|
||||||
group_by: ['job']
|
|
||||||
group_wait: 30s
|
|
||||||
group_interval: 5m
|
|
||||||
repeat_interval: 12h
|
|
||||||
routes:
|
|
||||||
{routes}
|
|
||||||
receivers:
|
|
||||||
- name: 'null'
|
|
||||||
{receivers}"#
|
|
||||||
);
|
|
||||||
|
|
||||||
info!("alert manager config: {}", alertmanager_config);
|
|
||||||
alertmanager_config
|
|
||||||
}
|
|
||||||
|
|
||||||
HelmChartScore {
|
|
||||||
namespace: Some(NonBlankString::from_str(&config.namespace).unwrap()),
|
|
||||||
release_name: NonBlankString::from_str("kube-prometheus").unwrap(),
|
|
||||||
chart_name: NonBlankString::from_str(
|
|
||||||
"oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
chart_version: None,
|
|
||||||
values_overrides: None,
|
|
||||||
values_yaml: Some(values.to_string()),
|
|
||||||
create_namespace: true,
|
|
||||||
install_only: true,
|
|
||||||
repository: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn discord_alert_builder(release_name: &String) -> (String, String) {
|
|
||||||
let discord_receiver_name = format!("Discord-{}", release_name);
|
|
||||||
let receiver = format!(
|
|
||||||
r#"
|
|
||||||
- name: '{discord_receiver_name}'
|
|
||||||
webhook_configs:
|
|
||||||
- url: 'http://{release_name}-alertmanager-discord:9094'
|
|
||||||
send_resolved: true"#,
|
|
||||||
);
|
|
||||||
let route = format!(
|
|
||||||
r#"
|
|
||||||
- receiver: '{discord_receiver_name}'
|
|
||||||
matchers:
|
|
||||||
- alertname!=Watchdog
|
|
||||||
continue: true"#,
|
|
||||||
);
|
|
||||||
(receiver, route)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn slack_alert_builder(slack_channel: &String) -> (String, String) {
|
|
||||||
let slack_receiver_name = format!("Slack-{}", slack_channel);
|
|
||||||
let receiver = format!(
|
|
||||||
r#"
|
|
||||||
- name: '{slack_receiver_name}'
|
|
||||||
slack_configs:
|
|
||||||
- channel: '{slack_channel}'
|
|
||||||
send_resolved: true
|
|
||||||
title: '{{{{ .CommonAnnotations.title }}}}'
|
|
||||||
text: '{{{{ .CommonAnnotations.description }}}}'"#,
|
|
||||||
);
|
|
||||||
let route = format!(
|
|
||||||
r#"
|
|
||||||
- receiver: '{slack_receiver_name}'
|
|
||||||
matchers:
|
|
||||||
- alertname!=Watchdog
|
|
||||||
continue: true"#,
|
|
||||||
);
|
|
||||||
(receiver, route)
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
mod kube_prometheus;
|
|
||||||
pub mod monitoring_alerting;
|
|
||||||
mod discord_alert_manager;
|
|
||||||
mod config;
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
use async_trait::async_trait;
|
|
||||||
use email_address::EmailAddress;
|
|
||||||
|
|
||||||
use log::info;
|
|
||||||
use serde::Serialize;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
data::{Id, Version},
|
|
||||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
|
||||||
inventory::Inventory,
|
|
||||||
score::Score,
|
|
||||||
topology::{HelmCommand, Topology},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
config::KubePrometheusConfig, discord_alert_manager::discord_alert_manager_score,
|
|
||||||
kube_prometheus::kube_prometheus_helm_chart_score,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub enum AlertChannel {
|
|
||||||
Discord {
|
|
||||||
name: String,
|
|
||||||
webhook_url: Url,
|
|
||||||
},
|
|
||||||
Slack {
|
|
||||||
slack_channel: String,
|
|
||||||
webhook_url: Url,
|
|
||||||
},
|
|
||||||
//TODO test and implement in helm chart
|
|
||||||
//currently does not work
|
|
||||||
Smpt {
|
|
||||||
email_address: EmailAddress,
|
|
||||||
service_name: String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct MonitoringAlertingStackScore {
|
|
||||||
pub alert_channel: Vec<AlertChannel>,
|
|
||||||
pub namespace: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MonitoringAlertingStackScore {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
alert_channel: Vec::new(),
|
|
||||||
namespace: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Topology + HelmCommand> Score<T> for MonitoringAlertingStackScore {
|
|
||||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
|
||||||
Box::new(MonitoringAlertingStackInterpret {
|
|
||||||
score: self.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("MonitoringAlertingStackScore")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
struct MonitoringAlertingStackInterpret {
|
|
||||||
score: MonitoringAlertingStackScore,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MonitoringAlertingStackInterpret {
|
|
||||||
async fn build_kube_prometheus_helm_chart_config(&self) -> KubePrometheusConfig {
|
|
||||||
let mut config = KubePrometheusConfig::new();
|
|
||||||
if let Some(ns) = &self.score.namespace {
|
|
||||||
config.namespace = ns.clone();
|
|
||||||
}
|
|
||||||
config.alert_channel = self.score.alert_channel.clone();
|
|
||||||
config
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn deploy_kube_prometheus_helm_chart_score<T: Topology + HelmCommand>(
|
|
||||||
&self,
|
|
||||||
inventory: &Inventory,
|
|
||||||
topology: &T,
|
|
||||||
config: &KubePrometheusConfig,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
let helm_chart = kube_prometheus_helm_chart_score(config);
|
|
||||||
helm_chart
|
|
||||||
.create_interpret()
|
|
||||||
.execute(inventory, topology)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn deploy_alert_channel_service<T: Topology + HelmCommand>(
|
|
||||||
&self,
|
|
||||||
inventory: &Inventory,
|
|
||||||
topology: &T,
|
|
||||||
config: &KubePrometheusConfig,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
let mut outcomes = vec![];
|
|
||||||
|
|
||||||
for channel in &self.score.alert_channel {
|
|
||||||
let outcome = match channel {
|
|
||||||
AlertChannel::Discord { .. } => {
|
|
||||||
discord_alert_manager_score(config)
|
|
||||||
.create_interpret()
|
|
||||||
.execute(inventory, topology)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
AlertChannel::Slack { .. } => Ok(Outcome::success(
|
|
||||||
"No extra configs for slack alerting".to_string(),
|
|
||||||
)),
|
|
||||||
AlertChannel::Smpt { .. } => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
outcomes.push(outcome);
|
|
||||||
}
|
|
||||||
for result in outcomes {
|
|
||||||
result?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Outcome::success("All alert channels deployed".to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<T: Topology + HelmCommand> Interpret<T> for MonitoringAlertingStackInterpret {
|
|
||||||
async fn execute(
|
|
||||||
&self,
|
|
||||||
inventory: &Inventory,
|
|
||||||
topology: &T,
|
|
||||||
) -> Result<Outcome, InterpretError> {
|
|
||||||
let config = self.build_kube_prometheus_helm_chart_config().await;
|
|
||||||
info!("Built kube prometheus config");
|
|
||||||
info!("Installing kube prometheus chart");
|
|
||||||
self.deploy_kube_prometheus_helm_chart_score(inventory, topology, &config)
|
|
||||||
.await?;
|
|
||||||
info!("Installing alert channel service");
|
|
||||||
self.deploy_alert_channel_service(inventory, topology, &config)
|
|
||||||
.await?;
|
|
||||||
Ok(Outcome::success(format!(
|
|
||||||
"succesfully deployed monitoring and alerting stack"
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self) -> InterpretName {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_version(&self) -> Version {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_status(&self) -> InterpretStatus {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_children(&self) -> Vec<Id> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -36,20 +36,13 @@ impl OKDBootstrapDhcpScore {
|
|||||||
.expect("Should have at least one worker to be used as bootstrap node")
|
.expect("Should have at least one worker to be used as bootstrap node")
|
||||||
.clone(),
|
.clone(),
|
||||||
});
|
});
|
||||||
// TODO refactor this so it is not copy pasted from dhcp.rs
|
|
||||||
Self {
|
Self {
|
||||||
dhcp_score: DhcpScore::new(
|
dhcp_score: DhcpScore::new(
|
||||||
host_binding,
|
host_binding,
|
||||||
// TODO : we should add a tftp server to the topology instead of relying on the
|
// TODO : we should add a tftp server to the topology instead of relying on the
|
||||||
// router address, this is leaking implementation details
|
// router address, this is leaking implementation details
|
||||||
Some(topology.router.get_gateway()),
|
Some(topology.router.get_gateway()),
|
||||||
None, // To allow UEFI boot we cannot provide a legacy file
|
Some("bootx64.efi".to_string()),
|
||||||
Some("undionly.kpxe".to_string()),
|
|
||||||
Some("ipxe.efi".to_string()),
|
|
||||||
Some(format!(
|
|
||||||
"http://{}:8080/boot.ipxe",
|
|
||||||
topology.router.get_gateway()
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ pub struct OKDDhcpScore {
|
|||||||
|
|
||||||
impl OKDDhcpScore {
|
impl OKDDhcpScore {
|
||||||
pub fn new(topology: &HAClusterTopology, inventory: &Inventory) -> Self {
|
pub fn new(topology: &HAClusterTopology, inventory: &Inventory) -> Self {
|
||||||
let mut host_binding: Vec<HostBinding> = topology
|
let host_binding = topology
|
||||||
.control_plane
|
.control_plane
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -28,35 +28,13 @@ impl OKDDhcpScore {
|
|||||||
.clone(),
|
.clone(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
topology
|
|
||||||
.workers
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.for_each(|(index, topology_entry)| {
|
|
||||||
host_binding.push(HostBinding {
|
|
||||||
logical_host: topology_entry.clone(),
|
|
||||||
physical_host: inventory
|
|
||||||
.worker_host
|
|
||||||
.get(index)
|
|
||||||
.expect("There should be enough worker hosts to fill topology")
|
|
||||||
.clone(),
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
// TODO : we should add a tftp server to the topology instead of relying on the
|
// TODO : we should add a tftp server to the topology instead of relying on the
|
||||||
// router address, this is leaking implementation details
|
// router address, this is leaking implementation details
|
||||||
dhcp_score: DhcpScore {
|
dhcp_score: DhcpScore {
|
||||||
host_binding,
|
host_binding,
|
||||||
next_server: Some(topology.router.get_gateway()),
|
next_server: Some(topology.router.get_gateway()),
|
||||||
boot_filename: None,
|
boot_filename: Some("bootx64.efi".to_string()),
|
||||||
filename: Some("undionly.kpxe".to_string()),
|
|
||||||
filename64: Some("ipxe.efi".to_string()),
|
|
||||||
filenameipxe: Some(format!(
|
|
||||||
"http://{}:8080/boot.ipxe",
|
|
||||||
topology.router.get_gateway()
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,19 +116,3 @@ pub fn yaml(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify that a string is a valid(ish) ingress path
|
|
||||||
/// Panics if path does not start with `/`
|
|
||||||
#[proc_macro]
|
|
||||||
pub fn ingress_path(input: TokenStream) -> TokenStream {
|
|
||||||
let input = parse_macro_input!(input as LitStr);
|
|
||||||
let path_str = input.value();
|
|
||||||
|
|
||||||
match path_str.starts_with("/") {
|
|
||||||
true => {
|
|
||||||
let expanded = quote! {(#path_str.to_string()) };
|
|
||||||
return TokenStream::from(expanded);
|
|
||||||
}
|
|
||||||
false => panic!("Invalid ingress path"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ pub mod tui {
|
|||||||
/// async fn main() {
|
/// async fn main() {
|
||||||
/// let inventory = Inventory::autoload();
|
/// let inventory = Inventory::autoload();
|
||||||
/// let topology = HAClusterTopology::autoload();
|
/// let topology = HAClusterTopology::autoload();
|
||||||
/// let mut maestro = Maestro::new(inventory, topology);
|
/// let mut maestro = Maestro::new(inventory, topology, "local");
|
||||||
///
|
///
|
||||||
/// maestro.register_all(vec![
|
/// maestro.register_all(vec![
|
||||||
/// Box::new(SuccessScore {}),
|
/// Box::new(SuccessScore {}),
|
||||||
|
|||||||
@@ -40,11 +40,7 @@ pub struct CaddyGeneral {
|
|||||||
#[yaserde(rename = "TlsDnsOptionalField4")]
|
#[yaserde(rename = "TlsDnsOptionalField4")]
|
||||||
pub tls_dns_optional_field4: MaybeString,
|
pub tls_dns_optional_field4: MaybeString,
|
||||||
#[yaserde(rename = "TlsDnsPropagationTimeout")]
|
#[yaserde(rename = "TlsDnsPropagationTimeout")]
|
||||||
pub tls_dns_propagation_timeout: Option<MaybeString>,
|
pub tls_dns_propagation_timeout: MaybeString,
|
||||||
#[yaserde(rename = "TlsDnsPropagationTimeoutPeriod")]
|
|
||||||
pub tls_dns_propagation_timeout_period: Option<MaybeString>,
|
|
||||||
#[yaserde(rename = "TlsDnsPropagationDelay")]
|
|
||||||
pub tls_dns_propagation_delay: Option<MaybeString>,
|
|
||||||
#[yaserde(rename = "TlsDnsPropagationResolvers")]
|
#[yaserde(rename = "TlsDnsPropagationResolvers")]
|
||||||
pub tls_dns_propagation_resolvers: MaybeString,
|
pub tls_dns_propagation_resolvers: MaybeString,
|
||||||
pub accesslist: MaybeString,
|
pub accesslist: MaybeString,
|
||||||
@@ -86,8 +82,4 @@ pub struct CaddyGeneral {
|
|||||||
pub auth_to_tls: Option<i32>,
|
pub auth_to_tls: Option<i32>,
|
||||||
#[yaserde(rename = "AuthToUri")]
|
#[yaserde(rename = "AuthToUri")]
|
||||||
pub auth_to_uri: MaybeString,
|
pub auth_to_uri: MaybeString,
|
||||||
#[yaserde(rename = "ClientIpHeaders")]
|
|
||||||
pub client_ip_headers: MaybeString,
|
|
||||||
#[yaserde(rename = "CopyHeaders")]
|
|
||||||
pub copy_headers: MaybeString,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ pub struct DhcpInterface {
|
|||||||
pub netboot: Option<u32>,
|
pub netboot: Option<u32>,
|
||||||
pub nextserver: Option<String>,
|
pub nextserver: Option<String>,
|
||||||
pub filename64: Option<String>,
|
pub filename64: Option<String>,
|
||||||
pub filename: Option<String>,
|
|
||||||
pub filenameipxe: Option<String>,
|
|
||||||
#[yaserde(rename = "ddnsdomainalgorithm")]
|
#[yaserde(rename = "ddnsdomainalgorithm")]
|
||||||
pub ddns_domain_algorithm: Option<MaybeString>,
|
pub ddns_domain_algorithm: Option<MaybeString>,
|
||||||
#[yaserde(rename = "numberoptions")]
|
#[yaserde(rename = "numberoptions")]
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ pub struct OPNsense {
|
|||||||
#[yaserde(rename = "Pischem")]
|
#[yaserde(rename = "Pischem")]
|
||||||
pub pischem: Option<Pischem>,
|
pub pischem: Option<Pischem>,
|
||||||
pub ifgroups: Ifgroups,
|
pub ifgroups: Ifgroups,
|
||||||
pub dnsmasq: Option<RawXml>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for OPNsense {
|
impl From<String> for OPNsense {
|
||||||
@@ -167,7 +166,7 @@ pub struct Sysctl {
|
|||||||
pub struct SysctlItem {
|
pub struct SysctlItem {
|
||||||
pub descr: MaybeString,
|
pub descr: MaybeString,
|
||||||
pub tunable: String,
|
pub tunable: String,
|
||||||
pub value: MaybeString,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
@@ -280,7 +279,6 @@ pub struct User {
|
|||||||
pub scope: String,
|
pub scope: String,
|
||||||
pub groupname: Option<MaybeString>,
|
pub groupname: Option<MaybeString>,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
pub pwd_changed_at: Option<MaybeString>,
|
|
||||||
pub uid: u32,
|
pub uid: u32,
|
||||||
pub disabled: Option<u8>,
|
pub disabled: Option<u8>,
|
||||||
pub landing_page: Option<MaybeString>,
|
pub landing_page: Option<MaybeString>,
|
||||||
@@ -542,8 +540,6 @@ pub struct GeneralIpsec {
|
|||||||
preferred_oldsa: Option<MaybeString>,
|
preferred_oldsa: Option<MaybeString>,
|
||||||
disablevpnrules: Option<MaybeString>,
|
disablevpnrules: Option<MaybeString>,
|
||||||
passthrough_networks: Option<MaybeString>,
|
passthrough_networks: Option<MaybeString>,
|
||||||
user_source: Option<MaybeString>,
|
|
||||||
local_group: Option<MaybeString>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
|
||||||
@@ -1223,7 +1219,6 @@ pub struct Host {
|
|||||||
pub rr: String,
|
pub rr: String,
|
||||||
pub mxprio: MaybeString,
|
pub mxprio: MaybeString,
|
||||||
pub mx: MaybeString,
|
pub mx: MaybeString,
|
||||||
pub ttl: Option<MaybeString>,
|
|
||||||
pub server: String,
|
pub server: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -1238,7 +1233,6 @@ impl Host {
|
|||||||
rr,
|
rr,
|
||||||
server,
|
server,
|
||||||
mxprio: MaybeString::default(),
|
mxprio: MaybeString::default(),
|
||||||
ttl: Some(MaybeString::default()),
|
|
||||||
mx: MaybeString::default(),
|
mx: MaybeString::default(),
|
||||||
description: None,
|
description: None,
|
||||||
}
|
}
|
||||||
@@ -1427,7 +1421,7 @@ pub struct VirtualIp {
|
|||||||
#[yaserde(attribute = true)]
|
#[yaserde(attribute = true)]
|
||||||
pub version: String,
|
pub version: String,
|
||||||
#[yaserde(rename = "vip")]
|
#[yaserde(rename = "vip")]
|
||||||
pub vip: Option<Vip>,
|
pub vip: Vip,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ pub mod modules;
|
|||||||
|
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
#[cfg(test)]
|
||||||
#[cfg(e2e_test)]
|
mod test {
|
||||||
mod e2e_test {
|
|
||||||
use opnsense_config_xml::StaticMap;
|
use opnsense_config_xml::StaticMap;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
|
||||||
|
#[cfg(opnsenseendtoend)]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_public_sdk() {
|
async fn test_public_sdk() {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|||||||
@@ -179,21 +179,7 @@ impl<'a> DhcpConfig<'a> {
|
|||||||
|
|
||||||
pub fn set_boot_filename(&mut self, boot_filename: &str) {
|
pub fn set_boot_filename(&mut self, boot_filename: &str) {
|
||||||
self.enable_netboot();
|
self.enable_netboot();
|
||||||
|
self.get_lan_dhcpd().filename64 = Some(boot_filename.to_string());
|
||||||
self.get_lan_dhcpd().bootfilename = Some(boot_filename.to_string());
|
self.get_lan_dhcpd().bootfilename = Some(boot_filename.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_filename(&mut self, filename: &str) {
|
|
||||||
self.enable_netboot();
|
|
||||||
self.get_lan_dhcpd().filename = Some(filename.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_filename64(&mut self, filename64: &str) {
|
|
||||||
self.enable_netboot();
|
|
||||||
self.get_lan_dhcpd().filename64 = Some(filename64.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_filenameipxe(&mut self, filenameipxe: &str) {
|
|
||||||
self.enable_netboot();
|
|
||||||
self.get_lan_dhcpd().filenameipxe = Some(filenameipxe.to_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user