-
Notifications
You must be signed in to change notification settings - Fork 290
Spin up should check required variables #3213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spin up should check required variables #3213
Conversation
crates/loader/src/local.rs
Outdated
| }) | ||
| } | ||
|
|
||
| fn env_checker((key, val): (String, Variable)) -> anyhow::Result<(String, Variable)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function name needs to be more descriptive. What is it checking?
crates/loader/src/local.rs
Outdated
| }) | ||
| } | ||
|
|
||
| fn env_checker((key, val): (String, Variable)) -> anyhow::Result<(String, Variable)> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not clear why this takes a tuple rather than two parameters?
crates/loader/src/local.rs
Outdated
| let variables = variables | ||
| .into_iter() | ||
| .map(|(name, v)| Ok((name.to_string(), locked_variable(v)?))) | ||
| .map(|(name, v)| Self::env_checker((name.to_string(), locked_variable(v)?))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this here means appears to mean we can't even build the LockedApp without having the variables available. How does this worth with e.g. spin registry push or spin cloud deploy?
crates/loader/src/local.rs
Outdated
|
|
||
| fn env_checker((key, val): (String, Variable)) -> anyhow::Result<(String, Variable)> { | ||
| if val.default.is_none() { | ||
| if std::env::var(env_key(None, key.as_ref())).is_err() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't assume that variables will come from the host environment. They could come from Vault or Azure KeyVault - for example passwords or tokens would typically be stashed in vaults and it would be rude to demand users create dummy EVs for them. Variable sources are defined in the runtime config file - you can't validate them until you have the runtime config providers lined up.
crates/loader/src/local.rs
Outdated
|
|
||
| fn env_checker((key, val): (String, Variable)) -> anyhow::Result<(String, Variable)> { | ||
| if val.default.is_none() { | ||
| if std::env::var(env_key(None, key.as_ref())).is_err() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you know that the user is using the default prefix?
crates/loader/src/local.rs
Outdated
|
|
||
| fn env_checker((key, val): (String, Variable)) -> anyhow::Result<(String, Variable)> { | ||
| if val.default.is_none() { | ||
| if std::env::var(env_key(None, key.as_ref())).is_err() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The environment provider appears to support a dotenv_path setting to merge values from a file - not clear that this is respected here?
crates/loader/src/local.rs
Outdated
| let variables = variables | ||
| .into_iter() | ||
| .map(|(name, v)| Ok((name.to_string(), locked_variable(v)?))) | ||
| .map(|(name, v)| Self::env_checker((name.to_string(), locked_variable(v)?))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a nit, but doing this in the loader produces an error message that implies we can't understand the manifest (usually meaning invalid TOML or incorrect schema): that's potentially misleading.
|
I think adding a new hook before execution of the CLI for the variables factor in crates/trigger/src/cl as discussed offline earlier might be a better place to run the check. |
|
Interestingly, the test failing in CI doesn't fail locally. Investigating it at the moment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I stuffed up communication in my previous review, sorry. The Spin variables system allows the user to configure variables to be read from multiple different sources. You cannot rely on the environment being the only source. You need to rethink this PR to completely forget about the environment. It needs to go through a configured ProviderResolver or whatever it's called at the moment, the thing that gets set up in the VariablesFactor and checks all configured sources for values. That will do the environment lookup, and any other lookups - the validation code should not be attempting a partial emulation of its behaviour, you should just use what exists.
Cargo.toml
Outdated
| spin-runtime-factors = { path = "crates/runtime-factors" } | ||
| spin-telemetry = { path = "crates/telemetry", features = [ | ||
| "tracing-log-compat", | ||
| "tracing-log-compat", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a few of these unrelated layout changes - maybe turn off auto formatting for this file?
crates/factors-test/src/lib.rs
Outdated
| let toml_str = toml::to_string(manifest).context("failed serializing manifest")?; | ||
| let dir = tempfile::tempdir().context("failed creating tempdir")?; | ||
| // `foo` variable is set to require. As we're not providing a default value, env is checked. | ||
| std::env::set_var(env_key(None, "foo"), "baz"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still say we should be able to transform a TOML manifest into a LockedApp without doing validation on variables.
crates/trigger/src/cli/variables.rs
Outdated
| use spin_factors_executor::ExecutorHooks; | ||
| use spin_variables::{VariableProviderConfiguration, VariableSourcer}; | ||
|
|
||
| /// Implements TriggerHooks, sorting required variables |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorting? Maybe comment on why they need sorting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, sorting wasn't the right choice of words. It doesn't sort, but basically checks for variables based on the configuration available for each variable provider. Guess the right word would be "checker"
crates/trigger/src/cli/variables.rs
Outdated
| use spin_variables::{VariableProviderConfiguration, VariableSourcer}; | ||
|
|
||
| /// Implements TriggerHooks, sorting required variables | ||
| pub struct VariableSorterExecutorHooks { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the naming here. Why is it an "Executor" hook?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming choice was to reflect its implementation of the ExecutorHooks trait
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it's called ExecutorHooks now... fair enough then but probably good to change the comment! grin
crates/trigger/Cargo.toml
Outdated
| spin-telemetry = { path = "../telemetry" } | ||
| spin-variables = { path = "../variables" } | ||
| tokio = { workspace = true, features = ["fs", "rt"] } | ||
| toml = { workspace = true } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Ryan had tried to push TOML dependencies into the runtime config crate, so that the trigger crate was abstracted from the physical representation of the runtime config? (For e.g. SpinKube scenarios.) I am not sure though.
crates/trigger/src/cli/variables.rs
Outdated
| } | ||
|
|
||
| impl VariableSourcer for VariableSorterExecutorHooks { | ||
| fn variable_env_checker(&self, key: String, val: spin_app::Variable) -> anyhow::Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
variable_env_checker is a noun. I think the idea here is something like check_variable_has_value or check_variable_resolves.
crates/trigger/src/cli/variables.rs
Outdated
| return self.check(key, val, dotenv_path, prefix); | ||
| } | ||
|
|
||
| Err(anyhow::anyhow!("No environment variable provider found")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what "provider" refers to in this context. Have I misunderstood the purpose of this function and it's actually trying to check if the env provider is present?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd change that. It's meant to be "no default variable provided"
crates/variables/src/lib.rs
Outdated
| _ = std::env::set_current_dir(path); | ||
| } | ||
|
|
||
| match std::env::var(env_key(prefix, &key)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't do this. There are providers other than the environment one. It is legal for a variable to come from Vault or Azure KeyVault or the static provider rather than the environment one. I tried to stress this in my previous review, sorry - this is fundamental.
fed8aaa to
7501996
Compare
a7f928c to
435c22b
Compare
435c22b to
2fed8a1
Compare
New logic only allows no default variable before runtime if Provider it is of a Dynamic type Signed-off-by: Aminu Oluwaseun Joshua <[email protected]>
2fed8a1 to
b483012
Compare
|
Closing this PR in favour of #3265. The commit history is messy and almost impossible to resolve |
Closes #3115
The PR checks if the variable default isn't provided when required. The check is handled by a new hook:
VariableSorterExecutorHooks.Inspired by @itowlson's comment, new metadata has been added to
Providers.