add bootstrap kubernetes labels and validator management structs#9
add bootstrap kubernetes labels and validator management structs#9gregcusack merged 7 commits intoanza-xyz:mainfrom
Conversation
9d1d622 to
5495c3a
Compare
5495c3a to
5402d0e
Compare
5402d0e to
a4b6943
Compare
a4b6943 to
9596709
Compare
joncinque
left a comment
There was a problem hiding this comment.
Just some small comments, this is all going in the right direction!
| validators | ||
| .into_iter() | ||
| .collect::<Vec<_>>() // Collect into Vec and thread push | ||
| .par_iter() | ||
| .try_for_each(|validator| Self::push_image(validator.image())) |
There was a problem hiding this comment.
Since push_image is using Command::spawn internally, it creates a new process anyway, so the par_iter is a little overkill. You could have push_image return the process::Child and then iterate through them here with wait_with_output, and completely remove rayon
| let mut data: BTreeMap<String, ByteString> = BTreeMap::new(); | ||
| for (label, value) in secrets { | ||
| match value { | ||
| SecretType::Value { v } => { | ||
| data.insert(label, ByteString(v.into_bytes())); | ||
| } | ||
| SecretType::File { path } => { | ||
| let file_content = std::fs::read(&path) | ||
| .map_err(|err| format!("Failed to read file '{:?}': {}", path, err))?; | ||
| data.insert(label, ByteString(file_content)); | ||
| } | ||
| } |
There was a problem hiding this comment.
nit: you might be able to do this in one statement by collecting into a BTreeMap, ie:
let data = secrets.into_iter().map(|(label_value)| ... (label, ByteString(v.into_bytes()))).collect::<BTreeMap<_, _>>();
| pub fn create_secret( | ||
| secret_name: &str, | ||
| key_files: &[(PathBuf, &str)], //[pathbuf, key type] | ||
| secrets: HashMap<String, SecretType>, |
There was a problem hiding this comment.
nit: Since Secret takes a BTreeMap, you could just pass one in here directly
| #[derive(Debug)] | ||
| struct DockerPushThreadError { | ||
| message: String, | ||
| } | ||
|
|
||
| impl Display for DockerPushThreadError { | ||
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { | ||
| write!(f, "{}", self.message) | ||
| } | ||
| } | ||
|
|
||
| impl Error for DockerPushThreadError {} | ||
|
|
||
| impl From<String> for DockerPushThreadError { | ||
| fn from(message: String) -> Self { | ||
| DockerPushThreadError { message } | ||
| } | ||
| } | ||
|
|
||
| impl From<&str> for DockerPushThreadError { | ||
| fn from(message: &str) -> Self { | ||
| DockerPushThreadError { | ||
| message: message.to_string(), | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
nit: It might be easier to use thiserror https://docs.rs/thiserror/latest/thiserror/ to define this error. It could become as simple as:
#[derive(Debug, Error)]
#[error(transparent)]
struct DockerPushThreadError(#[from] String);
There was a problem hiding this comment.
i am learning so many things about rust! thanks Jon!
There was a problem hiding this comment.
turns out i can actually just fully remove this whole thing based on the suggested change to push_image()
There was a problem hiding this comment.
Even better, no code is the best code 🧘
| ) -> Result<(), Box<dyn std::error::Error>> { | ||
| let so_filename = format!("spl_{}-{}.so", name.replace('-', "_"), version); | ||
| let so_path = solana_root_path.join(&so_filename); | ||
| let so_name = format!("spl_{}.so", name.replace('-', "_")); |
There was a problem hiding this comment.
ya it's a little weird since the url we are getting uses the GenesisProgram name with both hyphens and underscores
There was a problem hiding this comment.
Sorry, I meant that more as "sorry that we made this confusing for you" 😅
There was a problem hiding this comment.
e.g.: https://github.com/solana-labs/solana-program-library/releases/download/token-2022-v1.0.0/spl_token_2022.so uses the name token-2022 and token_2022
There was a problem hiding this comment.
ohhhhh haha ok nvm lol
| // 3) RPC Node -> One image for each RPC node (not implemented yet) | ||
| // 4) Clients -> Each client has its own image (not implemented yet) | ||
|
|
||
| pub struct Library { |
There was a problem hiding this comment.
nit: why the name Library? Seems like this is just all the machines / nodes / validators, so maybe a clearer name would help?
There was a problem hiding this comment.
ya def not the best name. i will change.
| // 4) Clients -> Each client has its own image (not implemented yet) | ||
|
|
||
| pub struct Library { | ||
| validators: Vec<Option<Validator>>, |
There was a problem hiding this comment.
This is a bit strange... how about separating the bootstrap validator into an Option<Validator> and then having validators as a Vec<Validator>?
There was a problem hiding this comment.
I agree it is a little weird. but it's basically used to store images and associated data. bootstrap, standard, rpc validators all use their own image for all validator types deployed. So a bootstrap, standard validator, and RPC would each only appear once in this Library. But for a Client, each client uses a different image, so that is why there is a vector of clients. This was the desired state with everything implemented: https://github.com/anza-xyz/validator-lab/pull/36/files#diff-47af127d675e3dc21b43c34222f42b9290334e88eb5c7ae0fc8b7539e3ecb794. But it may not be super clear.
i can change this to something like:
pub struct ValidatorImages { //struct name tbd
bootstrap: Option<Validator>,
standard: Option<Validator>,
rpc: Option<Validator>,
client: Vec<Validator>,
}
Note: we don't need a vector for standard or rpc since we only need one image per set of validators. Although i could change this if we want to store refactor a little more.
Do something like:
pub struct Cluster { //struct name tbd
bootstrap: Option<Validator>,
standard: Vec<Validator>,
rpc: Vec<Validator>,
client: Vec<Validator>,
}
and then import the kubernetes.rs functionality here. so in main we could do something like:
cluster.create_and_deploy_validators()
^ and this would create all the labels, selectors, secrets, replicasets, etc for the non-bootstrap validators. and then would deploy all the validators.
And can do the same for bootstrap, rpc, clients.
There was a problem hiding this comment.
I like that first option, it seems clearest to me at least.
And maybe we can split the difference on the name, and go with ClusterImages since the client isn't a validator? But I like both of the options 😄
There was a problem hiding this comment.
ok cool sounds good! and yes true
|
|
||
| pub struct Library { | ||
| validators: Vec<Option<Validator>>, | ||
| _clients: Option<Vec<Validator>>, |
There was a problem hiding this comment.
nit: it's up to you, but the Option part might be confusing, since there are two ways to represent no clients. Meaning, what's the difference between None and Some(vec![])?
… and update struct
… and update struct
* wip. adding replicaset but need validator config flags * add validator config * add pod requests. need for scheduling * create bootstrap validator replicaset * update token-2022 to v1.0.0: anza-xyz/agave#995 * address jon nits in #9 part 1. * jon comments from: #9 part 2. rename Library to ClusterImages and update struct * address Jon nits
Summary of Changes
rustls