Skip to content

Commit 5eb9d5d

Browse files
committed
version prefixing
1 parent 8d4ef12 commit 5eb9d5d

File tree

9 files changed

+83
-33
lines changed

9 files changed

+83
-33
lines changed

examples/deployment_reflector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn main() -> Result<(), failure::Error> {
1212
let config = config::load_kube_config().expect("failed to load kubeconfig");
1313
let client = APIClient::new(config);
1414

15-
let resource = ResourceType::Deploys(Some("kube-system".into()));
15+
let resource = ResourceType::V1Deployment(Some("kube-system".into()));
1616
let rf : Reflector<DeploymentSpec, DeploymentStatus> =
1717
Reflector::new(client, resource.into())
1818
.init()?;

examples/node_informer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() -> Result<(), failure::Error> {
1515
let config = config::load_kube_config().expect("failed to load kubeconfig");
1616
let client = APIClient::new(config);
1717

18-
let nodes = ResourceType::Nodes;
18+
let nodes = ResourceType::V1Node;
1919
let ni = Informer::new(client.clone(), nodes.into())
2020
.labels("role=worker")
2121
.init()?;

examples/node_reflector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn main() -> Result<(), failure::Error> {
1212
let config = config::load_kube_config().expect("failed to load kubeconfig");
1313
let client = APIClient::new(config);
1414

15-
let resource = ResourceType::Nodes;
15+
let resource = ResourceType::V1Node;
1616
let rf : Reflector<NodeSpec, NodeStatus> = Reflector::new(client, resource.into())
1717
.labels("role=master")
1818
.init()?;

examples/pod_informer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn main() -> Result<(), failure::Error> {
1414
let client = APIClient::new(config);
1515
let namespace = Some(env::var("NAMESPACE").unwrap_or("kube-system".into()));
1616

17-
let resource = ResourceType::Pods(namespace);
17+
let resource = ResourceType::V1Pod(namespace);
1818
let inf : Informer<PodSpec, PodStatus> = Informer::new(client.clone(), resource.into())
1919
.init()?;
2020

examples/pod_reflector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn main() -> Result<(), failure::Error> {
1212
let config = config::load_kube_config().expect("failed to load kubeconfig");
1313
let client = APIClient::new(config);
1414

15-
let resource = ResourceType::Pods(Some("kube-system".into()));
15+
let resource = ResourceType::V1Pod(Some("kube-system".into()));
1616
let rf : Reflector<PodSpec, PodStatus> = Reflector::new(client.clone(), resource.into())
1717
.init()?;
1818

src/api/informer.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use crate::api::Void;
12
use crate::api::resource::{
23
ResourceList,
34
WatchEvent,
45
ApiResource,
5-
QueryParams,
6+
GetParams,
67
};
78
use crate::client::APIClient;
89
use crate::{Result};
@@ -32,7 +33,7 @@ pub struct Informer<T, U> where
3233
version: Arc<RwLock<String>>,
3334
client: APIClient,
3435
resource: ApiResource,
35-
params: QueryParams,
36+
params: GetParams,
3637
}
3738

3839
impl<T, U> Informer<T, U> where
@@ -44,13 +45,13 @@ impl<T, U> Informer<T, U> where
4445
Informer {
4546
client,
4647
resource: r,
47-
params: QueryParams::default(),
48+
params: GetParams::default(),
4849
events: Arc::new(RwLock::new(VecDeque::new())),
4950
version: Arc::new(RwLock::new(0.to_string())),
5051
}
5152
}
5253

53-
// builders for QueryParams
54+
// builders for GetParams
5455

5556
/// Configure the timeout for the list/watch call.
5657
///
@@ -155,9 +156,7 @@ impl<T, U> Informer<T, U> where
155156
let req = self.resource.list_zero_resource_entries(&self.params)?;
156157

157158
// parse to void a ResourceList into void except for Metadata
158-
#[derive(Clone, Deserialize)]
159-
struct Discard {} // ffs
160-
let res = self.client.request::<ResourceList<Option<Discard>>>(req)?;
159+
let res = self.client.request::<ResourceList<Void>>(req)?;
161160

162161
let version = res.metadata.resourceVersion.unwrap_or_else(|| "0".into());
163162
debug!("Got fresh resourceVersion={} for {}", version, self.resource.resource);

src/api/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
//! API helpers to make use of k8s-openapi easier
22
3+
/// Empty struct for Void
4+
#[derive(Clone, Deserialize)]
5+
pub struct Discard {}
36
/// Shortcut type for discarding one type parameter option
4-
pub type Void = Option<()>;
7+
pub type Void = Option<Discard>;
58

69
mod reflector;
710
pub use self::reflector::{
@@ -19,7 +22,7 @@ pub use self::resource::{
1922
Resource,
2023
ApiResource,
2124
ResourceType,
22-
QueryParams,
25+
GetParams,
2326
WatchEvent,
2427
ApiError,
2528
};

src/api/reflector.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::api::resource::{
33
Resource,
44
WatchEvent,
55
ApiResource,
6-
QueryParams,
6+
GetParams,
77
};
88
use serde::de::DeserializeOwned;
99

@@ -35,7 +35,7 @@ pub struct Reflector<T, U> where
3535
version: Arc<RwLock<String>>,
3636
client: APIClient,
3737
resource: ApiResource,
38-
params: QueryParams,
38+
params: GetParams,
3939
}
4040

4141
impl<T, U> Reflector<T, U> where
@@ -47,13 +47,13 @@ impl<T, U> Reflector<T, U> where
4747
Reflector {
4848
client,
4949
resource: r,
50-
params: QueryParams::default(),
50+
params: GetParams::default(),
5151
data: Arc::new(RwLock::new(BTreeMap::new())),
5252
version: Arc::new(RwLock::new(0.to_string())),
5353
}
5454
}
5555

56-
// builders for QueryParams - TODO: defer to internal informer in future?
56+
// builders for GetParams - TODO: defer to internal informer in future?
5757
// for now, copy paste of informer's methods.
5858

5959
/// Configure the timeout for the list/watch call.

src/api/resource.rs

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,59 @@ use crate::{Result, Error};
1717
/// CustomResource purposefully ignored from this list.
1818
#[derive(Debug, Clone)]
1919
pub enum ResourceType {
20-
Nodes,
21-
Deploys(Option<String>),
22-
Pods(Option<String>),
20+
V1Node,
21+
V1Deployment(Option<String>),
22+
V1Pod(Option<String>),
23+
V1DaemonSet(Option<String>),
24+
V1ReplicaSet(Option<String>),
25+
V1StatefulSet(Option<String>),
2326
}
2427
impl Into<ApiResource> for ResourceType {
2528
fn into(self) -> ApiResource {
2629
match self {
27-
ResourceType::Nodes => ApiResource {
30+
ResourceType::V1Node => ApiResource {
2831
group: "".into(),
2932
resource: "nodes".into(),
3033
version: "v1".into(),
3134
namespace: None,
3235
prefix: "api".into()
3336
},
34-
ResourceType::Deploys(ns) => ApiResource {
37+
ResourceType::V1Deployment(ns) => ApiResource {
3538
group: "apps".into(),
3639
resource: "deployments".into(),
3740
version: "v1".into(),
3841
namespace: ns,
3942
prefix: "apis".into(),
4043
},
41-
ResourceType::Pods(ns) => ApiResource {
44+
ResourceType::V1Pod(ns) => ApiResource {
4245
group: "".into(),
4346
resource: "pods".into(),
4447
version: "v1".into(),
4548
namespace: ns,
4649
prefix: "api".into(),
4750
},
51+
ResourceType::V1DaemonSet(ns) => ApiResource {
52+
group: "apps".into(),
53+
resource: "daemonsets".into(),
54+
version: "v1".into(),
55+
namespace: ns,
56+
prefix: "apis".into(),
57+
},
58+
ResourceType::V1ReplicaSet(ns) => ApiResource {
59+
group: "apps".into(),
60+
resource: "replicasets".into(),
61+
version: "v1".into(),
62+
namespace: ns,
63+
prefix: "apis".into(),
64+
},
65+
ResourceType::V1StatefulSet(ns) => ApiResource {
66+
group: "apps".into(),
67+
resource: "statefulsets".into(),
68+
version: "v1".into(),
69+
namespace: ns,
70+
prefix: "apis".into(),
71+
},
4872
}
49-
5073
}
5174
}
5275

@@ -86,7 +109,7 @@ impl ToString for ApiResource {
86109
let g = if self.group == "" { "".into() } else { format!("{}/", self.group) };
87110
let v = if self.version == "" { "".into() } else { format!("{}/", self.version) };
88111
let n = if let Some(ns) = &self.namespace { format!("namespaces/{}/", ns) } else { "".into() };
89-
format!("/{prefix}{group}{version}{namespaces}{resource}?",
112+
format!("/{prefix}{group}{version}{namespaces}{resource}",
90113
prefix = pref,
91114
group = g,
92115
version = v,
@@ -101,7 +124,7 @@ impl ToString for ApiResource {
101124
/// Constructed internally with a builder on Informer and Reflector,
102125
/// but can be passed to the helper function of ApiResource.
103126
#[derive(Default, Clone)]
104-
pub struct QueryParams {
127+
pub struct GetParams {
105128
pub field_selector: Option<String>,
106129
pub include_uninitialized: bool,
107130
pub label_selector: Option<String>,
@@ -110,8 +133,8 @@ pub struct QueryParams {
110133

111134
impl ApiResource {
112135
/// Create a list request to fully re-fetch the state
113-
pub fn list_all_resource_entries(&self, par: &QueryParams) -> Result<http::Request<Vec<u8>>> {
114-
let mut qp = url::form_urlencoded::Serializer::new(self.to_string());
136+
pub fn list_all_resource_entries(&self, par: &GetParams) -> Result<http::Request<Vec<u8>>> {
137+
let mut qp = url::form_urlencoded::Serializer::new(self.to_string() + "?");
115138

116139
if let Some(fields) = &par.field_selector {
117140
qp.append_pair("fieldSelector", &fields);
@@ -129,8 +152,8 @@ impl ApiResource {
129152
}
130153

131154
/// Create a minimial list request to seed an initial resourceVersion
132-
pub fn list_zero_resource_entries(&self, par: &QueryParams) -> Result<http::Request<Vec<u8>>> {
133-
let mut qp = url::form_urlencoded::Serializer::new(self.to_string());
155+
pub fn list_zero_resource_entries(&self, par: &GetParams) -> Result<http::Request<Vec<u8>>> {
156+
let mut qp = url::form_urlencoded::Serializer::new(self.to_string() + "?");
134157
qp.append_pair("limit", "1"); // can't have 0..
135158
if par.include_uninitialized {
136159
qp.append_pair("includeUninitialized", "true");
@@ -142,8 +165,8 @@ impl ApiResource {
142165
}
143166

144167
/// Create watch request for a ApiResource at a given version
145-
pub fn watch_resource_entries_after(&self, par: &QueryParams, ver: &str) -> Result<http::Request<Vec<u8>>> {
146-
let mut qp = url::form_urlencoded::Serializer::new(self.to_string());
168+
pub fn watch_resource_entries_after(&self, par: &GetParams, ver: &str) -> Result<http::Request<Vec<u8>>> {
169+
let mut qp = url::form_urlencoded::Serializer::new(self.to_string() + "?");
147170

148171
qp.append_pair("watch", "true");
149172
qp.append_pair("resourceVersion", ver);
@@ -163,9 +186,34 @@ impl ApiResource {
163186
let mut req = http::Request::get(urlstr);
164187
req.body(vec![]).map_err(Error::from)
165188
}
189+
190+
pub fn replace_named_status(&self, name: &str) -> Result<http::Request<Vec<u8>>> {
191+
let base_url = format!("{base}/{name}/status", base = self.to_string(), name = name);
192+
let mut qp = url::form_urlencoded::Serializer::new(base_url);
193+
let urlstr = qp.finish();
194+
let mut req = http::Request::patch(urlstr);
195+
req.body(vec![]).map_err(Error::from)
196+
}
166197
}
167198

199+
#[test]
200+
fn get_paths(){
201+
let r : ApiResource = ResourceType::V1Deployment(Some("ns".into())).into();
202+
let gp = GetParams::default();
203+
let req = r.list_all_resource_entries(&gp).unwrap();
204+
assert_eq!(req.uri(), "/apis/apps/v1/namespaces/ns/deployments");
168205

206+
let r2 : ApiResource = ResourceType::V1Pod(Some("ns".into())).into();
207+
let req2 = r2.watch_resource_entries_after(&gp, "0").unwrap();
208+
assert_eq!(req2.uri(), "/api/v1/namespaces/ns/pods?&watch=true&resourceVersion=0&timeoutSeconds=10");
209+
}
210+
211+
#[test]
212+
fn replace_paths(){
213+
let r : ApiResource = ResourceType::V1Node.into();
214+
let req = r.replace_named_status("mynode").unwrap();
215+
assert_eq!(req.uri(), "/api/v1/nodes/mynode/status");
216+
}
169217

170218
// -------------------------------------------------------
171219

0 commit comments

Comments
 (0)