-
Notifications
You must be signed in to change notification settings - Fork 8
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
Yield more information about services to client #30
Changes from all commits
281c3db
0d02536
4a0b54e
02b10ee
26883e9
2f02c89
b4139a6
7833b92
399bc28
0a14228
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,10 +10,13 @@ use givc_common::types::*; | |
#[derive(Debug, Clone, PartialEq)] | ||
pub enum Placement { | ||
// Service is a `givc-agent` and could be directly connected | ||
Endpoint(EndpointEntry), | ||
Endpoint { endpoint: EndpointEntry, vm: String }, | ||
|
||
// Service or application managed by specified agent | ||
Managed(String), | ||
Managed { vm: String, by: String }, | ||
|
||
// Running on host | ||
Host, | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq)] | ||
|
@@ -26,14 +29,31 @@ pub struct RegistryEntry { | |
} | ||
|
||
impl RegistryEntry { | ||
pub fn agent_name(&self) -> Option<&str> { | ||
match &self.placement { | ||
Placement::Endpoint { .. } => Some(&self.name), | ||
Placement::Managed { by, .. } => Some(by), | ||
Placement::Host => None, | ||
} | ||
} | ||
|
||
pub fn vm_name(&self) -> Option<&str> { | ||
match &self.placement { | ||
Placement::Endpoint { vm, .. } => Some(vm), | ||
Placement::Managed { vm, .. } => Some(vm), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These branches could be combined with |
||
Placement::Host => None, | ||
} | ||
} | ||
|
||
pub fn agent(&self) -> anyhow::Result<&EndpointEntry> { | ||
match &self.placement { | ||
Placement::Endpoint(endpoint) => Ok(endpoint), | ||
Placement::Managed(by) => Err(anyhow!( | ||
Placement::Endpoint { endpoint, .. } => Ok(endpoint), | ||
Placement::Managed { by, .. } => Err(anyhow!( | ||
"Agent endpoint {} is managed by {}!", | ||
self.name, | ||
by | ||
)), | ||
Placement::Host => Err(anyhow!("Its a host!")), | ||
} | ||
} | ||
} | ||
|
@@ -57,13 +77,16 @@ impl RegistryEntry { | |
path: "bogus".to_string(), | ||
freezer_state: "bogus".to_string(), | ||
}, | ||
placement: Placement::Endpoint(EndpointEntry { | ||
address: EndpointAddress::Tcp { | ||
addr: "127.0.0.1".to_string(), | ||
port: 42, | ||
placement: Placement::Endpoint { | ||
endpoint: EndpointEntry { | ||
address: EndpointAddress::Tcp { | ||
addr: "127.0.0.1".to_string(), | ||
port: 42, | ||
}, | ||
tls_name: "bogus".to_string(), | ||
}, | ||
tls_name: "bogus".to_string(), | ||
}), | ||
vm: "bogus".into(), | ||
}, | ||
watch: true, | ||
} | ||
} | ||
|
@@ -89,7 +112,10 @@ impl TryFrom<pb::RegistryRequest> for RegistryEntry { | |
status, | ||
watch, | ||
r#type: ty, | ||
placement: Placement::Endpoint(endpoint), | ||
placement: Placement::Endpoint { | ||
endpoint, | ||
vm: "bogus".into(), | ||
}, | ||
}) | ||
} | ||
} | ||
|
@@ -103,11 +129,17 @@ impl From<RegistryEntry> for QueryResult { | |
} else { | ||
VMStatus::PoweredOff | ||
}; | ||
let vm_name = val.vm_name().map(|s| s.to_owned()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could use |
||
let agent_name = val.agent_name().map(|s| s.to_owned()); | ||
QueryResult { | ||
name: val.name, | ||
description: val.status.description, | ||
status, | ||
trust_level: TrustLevel::default(), | ||
vm_type: val.r#type.vm, | ||
service_type: val.r#type.service, | ||
vm_name, | ||
agent_name, | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
use std::collections::hash_map::HashMap; | ||
use std::sync::{Arc, Mutex}; | ||
|
||
use super::entry::{Placement, RegistryEntry}; | ||
use super::entry::RegistryEntry; | ||
use crate::types::*; | ||
use anyhow::{anyhow, bail}; | ||
use givc_common::query::{Event, QueryResult}; | ||
|
@@ -50,9 +50,12 @@ impl Registry { | |
Some(entry) => { | ||
let cascade: Vec<String> = state | ||
.values() | ||
.filter_map(|re| match &re.placement { | ||
Placement::Managed(within) if within == name => Some(re.name.clone()), | ||
_ => None, | ||
.filter_map(|re| { | ||
if re.agent_name() == Some(name) || re.vm_name() == Some(name) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe Tried to make it a one-liner, but the shortest I got was: |
||
Some(re.name.clone()) | ||
} else { | ||
None | ||
} | ||
}) | ||
.collect(); | ||
for each in cascade { | ||
|
@@ -173,6 +176,7 @@ impl Registry { | |
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::admin::entry::Placement; | ||
use crate::utils::naming::parse_application_name; | ||
|
||
#[test] | ||
|
@@ -204,11 +208,17 @@ mod tests { | |
let r = Registry::new(); | ||
let foo = RegistryEntry::dummy("foo".to_string()); | ||
let bar = RegistryEntry { | ||
placement: Placement::Managed("foo".into()), | ||
placement: Placement::Managed { | ||
by: "foo".into(), | ||
vm: "foo-vm".into(), | ||
}, | ||
..RegistryEntry::dummy("bar".to_string()) | ||
}; | ||
let baz = RegistryEntry { | ||
placement: Placement::Managed("foo".into()), | ||
placement: Placement::Managed { | ||
by: "foo".into(), | ||
vm: "foo-vm".into(), | ||
}, | ||
..RegistryEntry::dummy("baz".to_string()) | ||
}; | ||
|
||
|
@@ -219,12 +229,12 @@ mod tests { | |
assert!(r.contains("bar")); | ||
assert!(r.contains("baz")); | ||
|
||
r.deregister("baz"); | ||
r.deregister("baz")?; | ||
assert!(r.contains("foo")); | ||
assert!(r.contains("bar")); | ||
assert!(!r.contains("baz")); | ||
|
||
r.deregister("foo"); | ||
r.deregister("foo")?; | ||
assert!(!r.contains("foo")); | ||
assert!(!r.contains("bar")); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,14 +109,15 @@ impl AdminServiceImpl { | |
|
||
pub fn endpoint(&self, entry: &RegistryEntry) -> anyhow::Result<EndpointConfig> { | ||
let transport = match &entry.placement { | ||
Placement::Managed(parent) => { | ||
Placement::Managed { by: parent, .. } => { | ||
let parent = self.registry.by_name(parent)?; | ||
parent | ||
.agent() | ||
.with_context(|| "When get_remote_status()")? | ||
.to_owned() // Fail, if parent also `Managed` | ||
} | ||
Placement::Endpoint(endpoint) => endpoint.clone(), // FIXME: avoid clone! | ||
Placement::Endpoint { endpoint, .. } => endpoint.clone(), // FIXME: avoid clone! | ||
Placement::Host => bail!("endpoint() called for Host"), // impossible, FIXME: should never happens atm | ||
}; | ||
let tls_name = transport.tls_name.clone(); | ||
Ok(EndpointConfig { | ||
|
@@ -223,6 +224,10 @@ impl AdminServiceImpl { | |
} | ||
|
||
pub async fn handle_error(&self, entry: RegistryEntry) -> anyhow::Result<()> { | ||
info!( | ||
"Handling error for {} vm type {} service type {}", | ||
entry.name, entry.r#type.vm, entry.r#type.service | ||
); | ||
match (entry.r#type.vm, entry.r#type.service) { | ||
(VmType::AppVM, ServiceType::App) => { | ||
if entry.status.is_exitted() { | ||
|
@@ -232,10 +237,11 @@ impl AdminServiceImpl { | |
Ok(()) | ||
} | ||
(VmType::AppVM, ServiceType::Mgr) | (VmType::SysVM, ServiceType::Mgr) => { | ||
let name = parse_service_name(&entry.name)?; | ||
self.start_vm(name) | ||
.await | ||
.with_context(|| format!("handing error, by restart VM {}", entry.name))?; | ||
if let Placement::Managed { vm: vm_name, .. } = entry.placement { | ||
self.start_vm(&vm_name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if it makes a difference, but could move the |
||
.await | ||
.with_context(|| format!("handing error, by restart VM {}", entry.name))?; | ||
} | ||
Ok(()) // FIXME: should use `?` from line above, why it didn't work? | ||
} | ||
(x, y) => { | ||
|
@@ -305,27 +311,26 @@ impl AdminServiceImpl { | |
let name = req.app_name; | ||
let vm = req.vm_name.as_deref(); | ||
let vm_name = format_vm_name(&name, vm); | ||
let systemd_agent = format_service_name(&name, vm); | ||
let systemd_agent_name = format_service_name(&name, vm); | ||
|
||
info!("Starting app {name} on {vm_name}"); | ||
info!("Agent: {systemd_agent}"); | ||
info!("Starting app {name} on {vm_name} via {systemd_agent_name}"); | ||
|
||
// Entry unused in "go" code | ||
match self.registry.by_name(&systemd_agent) { | ||
match self.registry.by_name(&systemd_agent_name) { | ||
std::result::Result::Ok(e) => e, | ||
Err(_) => { | ||
info!("Starting up VM {vm_name}"); | ||
self.start_vm(&vm_name) | ||
.await | ||
.with_context(|| format!("Starting vm for {name}"))?; | ||
self.registry | ||
.by_name(&systemd_agent) | ||
.by_name(&systemd_agent_name) | ||
.context("after starting VM")? | ||
} | ||
}; | ||
let endpoint = self.agent_endpoint(&systemd_agent)?; | ||
let client = SystemDClient::new(endpoint.clone()); | ||
let app_name = self.registry.create_unique_entry_name(&name.to_string()); | ||
let endpoint = self.agent_endpoint(&systemd_agent_name)?; | ||
let client = SystemDClient::new(endpoint); | ||
let app_name = self.registry.create_unique_entry_name(&name); | ||
client.start_application(app_name.clone(), req.args).await?; | ||
let status = client.get_remote_status(app_name.clone()).await?; | ||
if status.active_state != "active" { | ||
|
@@ -340,7 +345,10 @@ impl AdminServiceImpl { | |
vm: VmType::AppVM, | ||
service: ServiceType::App, | ||
}, | ||
placement: Placement::Managed(systemd_agent), | ||
placement: Placement::Managed { | ||
by: systemd_agent_name, | ||
vm: vm_name, | ||
}, | ||
}; | ||
self.registry.register(app_entry); | ||
Ok(()) | ||
|
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
item.vm_type.parse().with_context(...)
would be more readable.