diff --git a/apps/variable-explorer/.gitignore b/apps/variable-explorer/.gitignore new file mode 100644 index 00000000..386474fa --- /dev/null +++ b/apps/variable-explorer/.gitignore @@ -0,0 +1,2 @@ +target/ +.spin/ diff --git a/apps/variable-explorer/Cargo.lock b/apps/variable-explorer/Cargo.lock new file mode 100644 index 00000000..7aadc04b --- /dev/null +++ b/apps/variable-explorer/Cargo.lock @@ -0,0 +1,609 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "indexmap" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "routefinder" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0971d3c8943a6267d6bd0d782fdc4afa7593e7381a92a3df950ff58897e066b5" +dependencies = [ + "smartcow", + "smartstring", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "smartcow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "656fcb1c1fca8c4655372134ce87d8afdf5ec5949ebabe8d314be0141d8b5da2" +dependencies = [ + "smartstring", +] + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "spdx" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bde1398b09b9f93fc2fc9b9da86e362693e999d3a54a8ac47a99a5a73f638b" +dependencies = [ + "smallvec", +] + +[[package]] +name = "spin-macro" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13524474ab9f876586e29f954377a66ed14fcb646fc9893e6f0e762213ddbd86" +dependencies = [ + "anyhow", + "bytes", + "http", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "spin-sdk" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05d0c09c0935fbb586d0a76e0f14b26b23f421c5e11b81d7200d22c4ead1211" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "form_urlencoded", + "futures", + "http", + "once_cell", + "routefinder", + "serde", + "serde_json", + "spin-macro", + "thiserror", + "wit-bindgen", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "variable-explorer" +version = "0.1.0" +dependencies = [ + "anyhow", + "spin-sdk", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasm-encoder" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822b645bf4f2446b949776ffca47e2af60b167209ffb70814ef8779d299cd421" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e09bca7d6388637d27fb5edbeab11f56bfabcef8743c55ae34370e1e5030a071" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.10.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c853d3809fc9fccf3bc0ad63f4f51d8eefad0bacf88f957aa991c1d9b88b016e" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder 0.41.0", + "wasmparser 0.121.0", +] + +[[package]] +name = "wasmparser" +version = "0.116.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" +dependencies = [ + "indexmap", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.121.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953cf6a7606ab31382cb1caa5ae403e77ba70c7f8e12eeda167e7040d42bfda8" +dependencies = [ + "bitflags", + "indexmap", + "semver", +] + +[[package]] +name = "wit-bindgen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38726c54a5d7c03cac28a2a8de1006cfe40397ddf6def3f836189033a413bc08" +dependencies = [ + "bitflags", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8bf1fddccaff31a1ad57432d8bfb7027a7e552969b6c68d6d8820dcf5c2371f" +dependencies = [ + "anyhow", + "wit-component", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7200e565124801e01b7b5ddafc559e1da1b2e1bed5364d669cd1d96fb88722" +dependencies = [ + "anyhow", + "heck", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae33920ad8119fe72cf59eb00f127c0b256a236b9de029a1a10397b1f38bdbd" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.48", + "wit-bindgen-core", + "wit-bindgen-rust", + "wit-component", +] + +[[package]] +name = "wit-component" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "480cc1a078b305c1b8510f7c455c76cbd008ee49935f3a6c5fd5e937d8d95b1e" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.36.2", + "wasm-metadata", + "wasmparser 0.116.1", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43771ee863a16ec4ecf9da0fc65c3bbd4a1235c8e3da5f094b562894843dfa76" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", +] diff --git a/apps/variable-explorer/Cargo.toml b/apps/variable-explorer/Cargo.toml new file mode 100644 index 00000000..e310b43f --- /dev/null +++ b/apps/variable-explorer/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "variable-explorer" +authors = ["Thorsten Hans "] +description = "" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +anyhow = "1" +spin-sdk = "2.2.0" + +[workspace] diff --git a/apps/variable-explorer/spin.toml b/apps/variable-explorer/spin.toml new file mode 100644 index 00000000..978f9e5d --- /dev/null +++ b/apps/variable-explorer/spin.toml @@ -0,0 +1,29 @@ +spin_manifest_version = 2 + +[application] +name = "variable-explorer" +version = "0.1.0" +authors = ["Thorsten Hans "] +description = "" + +[variables] +log_level = { default = "WARN" } +platform_name = { default = "Fermyon Cloud" } +db_password = { required = true } + +[[trigger.http]] +route = "/..." +component = "variable-explorer" + +[component.variable-explorer] +source = "target/wasm32-wasi/release/variable_explorer.wasm" +allowed_outbound_hosts = [] + +[component.variable-explorer.variables] +log_level = "{{ log_level }}" +platform_name = "{{ platform_name }}" +db_password = "{{ db_password }}" + +[component.variable-explorer.build] +command = "cargo build --target wasm32-wasi --release" +watch = ["src/**/*.rs", "Cargo.toml"] diff --git a/apps/variable-explorer/src/lib.rs b/apps/variable-explorer/src/lib.rs new file mode 100644 index 00000000..a50f1abf --- /dev/null +++ b/apps/variable-explorer/src/lib.rs @@ -0,0 +1,20 @@ +use spin_sdk::http::{IntoResponse, Request, Response}; +use spin_sdk::{http_component, variables}; + +/// A simple Spin HTTP component. +#[http_component] +fn handle_variable_explorer(_req: Request) -> anyhow::Result { + let log_level = variables::get("log_level")?; + let platform_name = variables::get("platform_name")?; + let db_password = variables::get("db_password")?; + + println!("# Log Level: {}", log_level); + println!("# Platform name: {}", platform_name); + println!("# DB Password: {}", db_password); + + Ok(Response::builder() + .status(200) + .header("content-type", "text/plain") + .body(format!("Hell from {}", platform_name)) + .build()) +} diff --git a/config/samples/variable-explorer.yaml b/config/samples/variable-explorer.yaml new file mode 100644 index 00000000..5d679e4a --- /dev/null +++ b/config/samples/variable-explorer.yaml @@ -0,0 +1,37 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: spin-app-cfg +data: + logLevel: INFO +--- +kind: Secret +apiVersion: v1 +metadata: + name: spin-app-secret +data: + password: c2VjcmV0X3NhdWNlCg== +--- +kind: SpinApp +apiVersion: core.spinoperator.dev/v1 +metadata: + name: variable-explorer +spec: + replicas: 1 + image: ttl.sh/variable-explorer:1h + executor: containerd-shim-spin + variables: + - name: platform_name + value: Kubernetes + - name: log_level + valueFrom: + configMapKeyRef: + name: spin-app-cfg + key: logLevel + optional: true + - name: db_password + valueFrom: + secretKeyRef: + name: spin-app-secret + key: password + optional: false \ No newline at end of file diff --git a/documentation/content/assigning-variables-to-spinapps.md b/documentation/content/assigning-variables-to-spinapps.md new file mode 100644 index 00000000..44ac50ba --- /dev/null +++ b/documentation/content/assigning-variables-to-spinapps.md @@ -0,0 +1,153 @@ +- [Assigning variables to SpinApps](#assigning-variables-to-spinapps) + - [Prerequisites](#prerequisites) + - [Build and Store SpinApp in an OCI Registry](#build-and-store-spinapp-in-an-oci-registry) + - [Configration data in Kubernetes](#configration-data-in-kubernetes) + - [Assigning variables to a SpinApp](#assigning-variables-to-a-spinapp) + - [Inspecting runtime logs of your SpinApp](#inspecting-runtime-logs-of-your-spinapp) + +# Assigning variables to SpinApps + +By using variables, you can alter application behavior without recompiling your SpinApp. When running in Kubernetes (k8s), you can either provide constant values for variables, or reference them from Kubernetes primitives such as `ConfigMaps` and `Secrets`. This tutorial guides your through the process of assigning variables to your `SpinApp`. + +## Prerequisites + +Ensure necessary [prerequisites](./prerequisites.md) are installed. + +For this tutorial in particular, you should either have the Spin Operator [running locally](./running-locally.md) or [running on your Kubernetes cluster](./running-on-a-cluster.md). + +## Build and Store SpinApp in an OCI Registry + +We’re going to build the SpinApp and store it inside of a [ttl.sh](http://ttl.sh) registry. Move into the [apps/variable-explorer](../../apps/variable-explorer) directory and build the SpinApp we’ve provided: + +```bash +# Build and publish the sample app +cd apps/variable-explorer +spin build +spin registry push ttl.sh/variable-explorer:1h +``` + +Note that the tag at the end of [ttl.sh/variable-explorer:1h](http://ttl.sh/variable-explorer:1h) indicates how long the image will last e.g. `1h` (1 hour). The maximum is `24h` and you will need to repush if ttl exceeds 24 hours. + +For demonstration purposes, we use the [variable explorer](../../apps/variable-explorer) sample app. It reads three different variables (`log_level`, `platform_name` and `db_password`) and prints their values to the `STDOUT` stream as shown in the following snippet: + +```rust +let log_level = variables::get("log_level")?; +let platform_name = variables::get("platform_name")?; +let db_password = variables::get("db_password")?; + +println!("# Log Level: {}", log_level); +println!("# Platform name: {}", platform_name); +println!("# DB Password: {}", db_password); +``` + +Those variables are defined as part of the Spin manifest (`spin.toml`), and access to them is granted to the `variable-explorer` component: + +```toml +[variables] +log_level = { default = "WARN" } +platform_name = { default = "Fermyon Cloud" } +db_password = { required = true } + +[component.variable-explorer.variables] +log_level = "{{ log_level }}" +platform_name = "{{ platform_name }}" +db_password = "{{ db_password }}" +``` + +## Configration data in Kubernetes + +In Kubernetes, you use `ConfigMaps` for storing non-senstive, and `Secrets` for storing sesitive configuration data. The deployment manifest (`config/samples/variable-explorer.yaml`) contains specifications for both a `ConfigMap` and a `Secret`: + +```yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: spinapp-cfg +data: + logLevel: INFO +--- +kind: Secret +apiVersion: v1 +metadata: + name: spinapp-secret +data: + password: c2VjcmV0X3NhdWNlCg== +``` + +## Assigning variables to a SpinApp + +When creating a `SpinApp`, you can choose from different approaches for specifying variables: + +1. Providing constant values +2. Loading configuration values from ConfigMaps +3. Loading configuration values from Secrets + +The `SpinApp` specification contains the `variables` array, that you use for specifying variables (See `kubectl explain spinapp.spec.variables`). + +The deployment manifest (`config/samples/variable-explorer.yaml`) specifies a static value for `platform_name`. The value of `log_level` is read from the `ConfigMap` called `spinapp-cfg`, and the `db_password` is read from the `Secert` called `spinapp-secret`: + +```yaml +kind: SpinApp +apiVersion: core.spinoperator.dev/v1 +metadata: + name: variable-explorer +spec: + replicas: 1 + image: ttl.sh/variable-explorer:1h + executor: containerd-shim-spin + variables: + - name: platform_name + value: Kubernetes + - name: log_level + valueFrom: + configMapKeyRef: + name: spinapp-cfg + key: logLevel + optional: true + - name: db_password + valueFrom: + secretKeyRef: + name: spinapp-secret + key: password + optional: false +``` + +As the deployment manifest outlines, you can use the `optional` property - as you would do when specifying environment variables for a regular Kubernetes `Pod` - to control if Kubernetes should prevent starting the SpinApp, if the referenced configuration source does not exist. + +You can deploy all resources by executing the following command: + +```bash +kubectl apply -f config/samples/variable-explorer.yaml + +configmap/spinapp-cfg created +secret/spinapp-secret created +spinapp.core.spinoperator.dev/variable-explorer created +``` + +## Inspecting runtime logs of your SpinApp + +To verify that all variables are passed correctly to the SpinApp, you can configure port forwarding from your local machine to the corresponding Kubernetes `Service`: + +```bash +kubectl port-forward services/variable-explorer 8080:80 + +Forwarding from 127.0.0.1:8080 -> 80 +Forwarding from [::1]:8080 -> 80 +``` + +When port forwarding is established, you can send an HTTP request to the variable-explorer from within an additional terminal session: + +```bash +curl http://lcoalhost:8080 +Hello from Kubernetes +``` + +Finally, you can use `kubectl logs` to see all logs produced by the variable-explorer at runtime: + +```bash +kubectl logs -l core.spinoperator.dev/app-name=variable-explorer + +# Log Level: INFO +# Platform Name: Kubernetes +# DB Password: secret_sauce +```