Skip to content

Commit

Permalink
Set up code coverage properly (#740)
Browse files Browse the repository at this point in the history
* code coverage improvement testing

Signed-off-by: clux <sszynrae@gmail.com>

* codecov action

Signed-off-by: clux <sszynrae@gmail.com>

* try newer k3d action

Signed-off-by: clux <sszynrae@gmail.com>

* wtf

Signed-off-by: clux <sszynrae@gmail.com>

* get coverage running above 55

still not getting all the results i want because some ignored tests are
not running

Signed-off-by: clux <sszynrae@gmail.com>

* remove duplicate instructions and leftovers

Signed-off-by: clux <sszynrae@gmail.com>

* fmt + comment

Signed-off-by: clux <sszynrae@gmail.com>

* simplify (tarpaulin does not inject features in workspaces anyway)

Signed-off-by: clux <sszynrae@gmail.com>

* fix test feature requirement

Signed-off-by: clux <sszynrae@gmail.com>

* need to move cfg limit before module

Signed-off-by: clux <sszynrae@gmail.com>

* try running doc tests as well

Signed-off-by: clux <sszynrae@gmail.com>

* try using nightly for tarpaulin doc test runner

Signed-off-by: clux <sszynrae@gmail.com>

* try with two runs of tarpaulin

Signed-off-by: clux <sszynrae@gmail.com>

* simplified with one-pass on stable

Signed-off-by: clux <sszynrae@gmail.com>

* test 3 core methods

Signed-off-by: clux <sszynrae@gmail.com>

* import parts of dynamic api example as discovery tests

Signed-off-by: clux <sszynrae@gmail.com>

* remove accidentally left-in flags

Signed-off-by: clux <sszynrae@gmail.com>

* revert pointless change in core_methods

Signed-off-by: clux <sszynrae@gmail.com>
  • Loading branch information
clux authored Dec 6, 2021
1 parent 20642bb commit c88addd
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 40 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Coverage

on:
push:
#branches:
# - master

jobs:
rust:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- uses: Swatinem/rust-cache@v1
- uses: AbsaOSS/k3d-action@v2
name: "Create Single Cluster"
with:
cluster-name: "test-cluster-1"
args: >-
--agents 1
--image docker.io/rancher/k3s:v1.22.4-k3s1
--k3s-arg "--no-deploy=traefik,servicelb,metrics-server@server:*"
- name: Run cargo-tarpaulin
uses: actions-rs/tarpaulin@v0.1
with:
version: '0.18.5'
out-type: Xml
args: ' -- --test-threads 1'
- uses: codecov/codecov-action@v2
22 changes: 0 additions & 22 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,3 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
body_path: release.txt
code-coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Run cargo-tarpaulin
uses: actions-rs/tarpaulin@v0.1
with:
version: '0.18.0'
out-type: Lcov
timeout: 600
args: '--all -e tests -- --test-threads 1'
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./lcov.info
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ test:

test-kubernetes:
cargo test --lib --all -- --ignored # also run tests that fail on github actions
cargo test -p kube --features=derive -- --ignored
cargo test -p kube --lib --features=derive,runtime -- --ignored
cargo run -p kube-examples --example crd_derive
cargo run -p kube-examples --example crd_api

Expand Down
1 change: 0 additions & 1 deletion kube-core/src/admission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub struct SerializePatchError(#[source] serde_json::Error);
/// Failed to convert `AdmissionReview` into `AdmissionRequest`.
pub struct ConvertAdmissionReviewError;


/// The `kind` field in [`TypeMeta`].
pub const META_KIND: &str = "AdmissionReview";
/// The `api_version` field in [`TypeMeta`] on the v1 version.
Expand Down
2 changes: 2 additions & 0 deletions kube-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,10 @@ mod custom_resource;
/// If you have to override a lot, [you can opt-out of schema-generation entirely](#kubeschema--mode)
///
/// ## Advanced Features
///
/// - **embedding k8s-openapi types** can be done by enabling the `schemars` feature of `k8s-openapi` from [`0.13.0`](https://github.com/Arnavion/k8s-openapi/blob/master/CHANGELOG.md#v0130-2021-08-09)
/// - **adding validation** via [validator crate](https://github.com/Keats/validator) is supported from `schemars` >= [`0.8.5`](https://github.com/GREsau/schemars/blob/master/CHANGELOG.md#085---2021-09-20)
/// - **generating rust code from schemas** can be done via [kopium](https://github.com/kube-rs/kopium) and is supported on stable crds (> 1.16 kubernetes)
///
/// ### Validation Caveats
/// The supported **`#[validate]` attrs also exist as `#[schemars]` attrs** so you can use those directly if you do not require the validation to run client-side (in your code).
Expand Down
121 changes: 105 additions & 16 deletions kube/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,26 +179,37 @@ pub use crate::core::{CustomResourceExt, Resource, ResourceExt};
#[doc(inline)]
pub use kube_core as core;


// Tests that require a cluster and the complete feature set
// Can be run with `cargo test -p kube --lib --features=runtime,derive -- --ignored`
#[cfg(test)]
#[cfg(all(feature = "derive", feature = "client"))]
mod test {
#[cfg(all(feature = "derive", feature = "client"))]
use crate::{Api, Client, CustomResourceExt, ResourceExt};
use kube_derive::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
#[kube(group = "clux.dev", version = "v1", kind = "Foo", namespaced)]
#[kube(status = "FooStatus")]
#[kube(scale = r#"{"specReplicasPath":".spec.replicas", "statusReplicasPath":".status.replicas"}"#)]
#[kube(crates(kube_core = "crate::core"))] // for dev-dep test structure
pub struct FooSpec {
name: String,
info: Option<String>,
replicas: isize,
}

#[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
pub struct FooStatus {
is_bad: bool,
replicas: isize,
}

#[tokio::test]
#[ignore] // needs kubeconfig
async fn convenient_custom_resource() {
use crate::{
core::{ApiResource, DynamicObject, GroupVersionKind},
Api, Client, CustomResource,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, CustomResource, Deserialize, Serialize, JsonSchema)]
#[kube(group = "clux.dev", version = "v1", kind = "Foo", namespaced)]
#[kube(crates(kube_core = "crate::core"))]
struct FooSpec {
foo: String,
}
async fn custom_resource_generates_correct_core_structs() {
use crate::core::{ApiResource, DynamicObject, GroupVersionKind};
let client = Client::try_default().await.unwrap();

let gvk = GroupVersionKind::gvk("clux.dev", "v1", "Foo");
Expand All @@ -209,4 +220,82 @@ mod test {
// make sure they return the same url_path through their impls
assert_eq!(a1.resource_url(), a2.resource_url());
}

use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition;
#[tokio::test]
#[ignore] // needs cluster (creates + patches foo crd)
#[cfg(all(feature = "derive", feature = "runtime"))]
async fn derived_resource_queriable() -> Result<(), Box<dyn std::error::Error>> {
use crate::{
core::params::{DeleteParams, Patch, PatchParams},
runtime::wait::{await_condition, conditions},
};
let client = Client::try_default().await?;
let ssapply = PatchParams::apply("kube").force();
let crds: Api<CustomResourceDefinition> = Api::all(client.clone());
// Server-side apply CRD
crds.patch("foos.clux.dev", &ssapply, &Patch::Apply(Foo::crd()))
.await?;
// Wait for it to be ready:
let establish = await_condition(crds, "foos.clux.dev", conditions::is_crd_established());
let _ = tokio::time::timeout(std::time::Duration::from_secs(10), establish).await?;
// Use it
let foos: Api<Foo> = Api::default_namespaced(client.clone());
// Apply from generated struct
let foo = Foo::new("baz", FooSpec {
name: "baz".into(),
info: Some("old baz".into()),
replicas: 3,
});
let o = foos.patch("baz", &ssapply, &Patch::Apply(&foo)).await?;
assert_eq!(o.spec.name, "baz");
// Apply from partial json!
let patch = serde_json::json!({
"apiVersion": "clux.dev/v1",
"kind": "Foo",
"spec": {
"name": "foo",
"replicas": 2
}
});
let o2 = foos.patch("baz", &ssapply, &Patch::Apply(patch)).await?;
assert_eq!(o2.spec.replicas, 2);
assert_eq!(foos.get_scale("baz").await?.spec.unwrap().replicas, Some(2));
assert!(foos.get_status("baz").await?.status.is_none()); // nothing has set this
foos.delete("baz", &DeleteParams::default()).await?;
Ok(())
}

#[tokio::test]
#[ignore] // needs cluster (fetches api resources, and lists all)
#[cfg(all(feature = "derive", feature = "runtime"))]
async fn dynamic_resources_discoverable() -> Result<(), Box<dyn std::error::Error>> {
use crate::{
core::DynamicObject,
discovery::{verbs, Discovery, Scope},
};
let client = Client::try_default().await?;

let discovery = Discovery::new(client.clone()).run().await?;
for group in discovery.groups() {
for (ar, caps) in group.recommended_resources() {
if !caps.supports_operation(verbs::LIST) {
continue;
}
let api: Api<DynamicObject> = if caps.scope == Scope::Namespaced {
Api::default_namespaced_with(client.clone(), &ar)
} else {
Api::all_with(client.clone(), &ar)
};
println!("{}/{} : {}", group.name(), ar.version, ar.kind);
let list = api.list(&Default::default()).await?;
for item in list.items {
let name = item.name();
let ns = item.metadata.namespace.map(|s| s + "/").unwrap_or_default();
println!("\t\t{}{}", ns, name);
}
}
}
Ok(())
}
}
12 changes: 12 additions & 0 deletions tarpaulin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Usage cargo tarpaulin -- --test-threads 1

[one_pass_coverage]
workspace = true
features = "kube/derive kube/runtime"
color = "Always"
ignored = true
timeout = "600s"
exclude = ["integration"]
# NB: skipping Doctests because they are slow to build and generally marked no_run
run-types = ["Tests"]
generate = ["Json"]

0 comments on commit c88addd

Please sign in to comment.