Skip to content

Commit

Permalink
deploy: 7ea639c
Browse files Browse the repository at this point in the history
  • Loading branch information
YJDoc2 committed Feb 12, 2024
1 parent ef5cb60 commit 1fb7a00
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 93 deletions.
20 changes: 10 additions & 10 deletions developer/debugging.html
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ <h1 class="menu-title">Youki User and Developer Documentation</h1>
<main>
<h1 id="debugging"><a class="header" href="#debugging">Debugging</a></h1>
<p>Since Youki uses pipe and double-fork in the creating phase, it is hard to debug what happened.
You might encounter the error message, &quot;Broken pipe ...&quot; Unfortunately,
You might encounter the error message, "Broken pipe ..." Unfortunately,
this error message has only information that a child process exists with an error for some reason.</p>
<p>This section will give some tips to debug youki to know what happens in the child processes.</p>
<h1 id="bpftrace"><a class="header" href="#bpftrace">bpftrace</a></h1>
Expand Down Expand Up @@ -216,15 +216,15 @@ <h1 id="bpftrace"><a class="header" href="#bpftrace">bpftrace</a></h1>
$ just test-kind
docker buildx build --output=bin/ -f tests/k8s/Dockerfile --target kind-bin .
...
Creating cluster &quot;youki&quot; ...
Creating cluster "youki" ...
...
kubectl --context=kind-youki apply -f tests/k8s/deploy.yaml
runtimeclass.node.k8s.io/youki created
deployment.apps/nginx-deployment created
...
kubectl --context=kind-youki delete -f tests/k8s/deploy.yaml
runtimeclass.node.k8s.io &quot;youki&quot; deleted
deployment.apps &quot;nginx-deployment&quot; deleted
runtimeclass.node.k8s.io "youki" deleted
deployment.apps "nginx-deployment" deleted
</code></pre>
</li>
<li>
Expand All @@ -241,18 +241,18 @@ <h1 id="bpftrace"><a class="header" href="#bpftrace">bpftrace</a></h1>
207066996623 4 13743 open errno=2, fd=-1, file=/opt/containerd/lib/glibc-hwcaps/x86-64-v3/libc.so.6
...
207070130175 4 13743 clone3
207070418829 youki:[1:INTER] 13747 write fd=4, {&quot;timestamp&quot;:&quot;2023-09-24T10:47:07.427846Z&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;message&quot;:&quot;cgroup manager V2 will be used&quot;,&quot;target&quot;:&quot;libcgrou
207070418829 youki:[1:INTER] 13747 write fd=4, {"timestamp":"2023-09-24T10:47:07.427846Z","level":"INFO","message":"cgroup manager V2 will be used","target":"libcgrou
...
207084948440 youki:[1:INTER] 13747 clone3
207085058811 youki:[1:INTER] 13747 write fd=4, {&quot;timestamp&quot;:&quot;2023-09-24T10:47:07.442502Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;message&quot;:&quot;sending init pid (Pid(1305))&quot;,&quot;target&quot;:&quot;libcontai
207085343170 youki:[2:INIT] 13750 write fd=4, {&quot;timestamp&quot;:&quot;2023-09-24T10:47:07.442746Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;message&quot;:&quot;unshare or setns: LinuxNamespace { typ: Uts, path
207085058811 youki:[1:INTER] 13747 write fd=4, {"timestamp":"2023-09-24T10:47:07.442502Z","level":"DEBUG","message":"sending init pid (Pid(1305))","target":"libcontai
207085343170 youki:[2:INIT] 13750 write fd=4, {"timestamp":"2023-09-24T10:47:07.442746Z","level":"DEBUG","message":"unshare or setns: LinuxNamespace { typ: Uts, path
...
207088256843 youki:[2:INIT] 13750 pivt_root new_root=/run/containerd/io.containerd.runtime.v2.task/k8s.io/0fea8cf5f8d1619a35ca67fd6fa73d8d7c8fc70ac2ed43ee2ac2f8610bb938f6/r, put_old=/run/containerd/io.containerd.runtime.v2.task/k8s.io/0fea8cf5f8d1619a35ca67fd6fa73d8d7c8fc70ac2ed43ee2ac2f8610bb938f6/r
...
207097207551 youki:[2:INIT] 13750 write fd=4, {&quot;timestamp&quot;:&quot;2023-09-24T10:47:07.454645Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;message&quot;:&quot;found executable in executor&quot;,&quot;executable&quot;:&quot;\&quot;/pa
207097207551 youki:[2:INIT] 13750 write fd=4, {"timestamp":"2023-09-24T10:47:07.454645Z","level":"DEBUG","message":"found executable in executor","executable":"\"/pa
...
207139391811 youki:[2:INIT] 13750 write fd=4, {&quot;timestamp&quot;:&quot;2023-09-24T10:47:07.496815Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;message&quot;:&quot;received: start container&quot;,&quot;target&quot;:&quot;libcontainer
207139423243 youki:[2:INIT] 13750 write fd=4, {&quot;timestamp&quot;:&quot;2023-09-24T10:47:07.496868Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;message&quot;:&quot;executing workload with default handler&quot;,&quot;target&quot;
207139391811 youki:[2:INIT] 13750 write fd=4, {"timestamp":"2023-09-24T10:47:07.496815Z","level":"DEBUG","message":"received: start container","target":"libcontainer
207139423243 youki:[2:INIT] 13750 write fd=4, {"timestamp":"2023-09-24T10:47:07.496868Z","level":"DEBUG","message":"executing workload with default handler","target"

</code></pre>
</li>
Expand Down
2 changes: 1 addition & 1 deletion developer/e2e/runtimetest.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ <h2 id="notes"><a class="header" href="#notes">Notes</a></h2>
<p>Now runtimetest needs at least <code>oci-spec</code> and <code>nix</code> package for its operations, which are also dependencies of other packages in the workspace. Thus both of these, and recursively their dependencies must be compiled twice, each time, once for dynamic linking and once for static. The took a long time in the compilation stage, especially when developing / adding new tests. Separating runtimetest from the workspace allows it to have a separate target/ directory, where it can store the statically compiled dependencies, and the workspace can have its target/ directory, where it can store its dynamically compiled dependencies. That way only the crates which have changes need to be compiled (runtimetest or integration test), and not their dependencies.</p>
<p>In case in future this separation is not required, or some other configuration is chosen, make sure the multiple compilation issue does not arise, or the advantages of new method outweigh the time spent in double compilation.</p>
<p>To see if a binary can be run inside the container process, run</p>
<pre><code class="language-console">readelf -l path/to/binary |grep &quot;program interpreter&quot;
<pre><code class="language-console">readelf -l path/to/binary |grep "program interpreter"
</code></pre>
<p><code>[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]</code> means that the binary is not statically linked, and cannot be run inside the container process. If the above command gives no output, that means it does not require any program interpreter and can be run inside the container.</p>
<p>Another way is to run</p>
Expand Down
89 changes: 82 additions & 7 deletions developer/e2e/rust_oci_test.html
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,46 @@ <h1 id="how-to-write"><a class="header" href="#how-to-write">How to write</a></h
<details>
<summary>Fully the code of the example test</summary>
<p>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/integration_test/src/tests/example/hello_world.rs}}</code></pre>
<pre><code class="language-rust no_run noplayground">use anyhow::{Context, Result};
use oci_spec::runtime::{ProcessBuilder, Spec, SpecBuilder};
use test_framework::{test_result, Test, TestGroup, TestResult};

use crate::utils::test_inside_container;

////////// ANCHOR: get_example_spec
fn create_spec() -&gt; Result&lt;Spec&gt; {
SpecBuilder::default()
.process(
ProcessBuilder::default()
.args(
["runtimetest", "hello_world"]
.iter()
.map(|s| s.to_string())
.collect::&lt;Vec&lt;String&gt;&gt;(),
)
.build()?,
)
.build()
.context("failed to create spec")
}
////////// ANCHOR_END: get_example_spec

////////// ANCHOR: example_test
fn example_test() -&gt; TestResult {
let spec = test_result!(create_spec());
test_inside_container(spec, &amp;|_| Ok(()))
}
////////// ANCHOR_END: example_test

////////// ANCHOR: get_example_test
pub fn get_example_test() -&gt; TestGroup {
let mut test_group = TestGroup::new("example");
let test1 = Test::new("hello world", Box::new(example_test));
test_group.add(vec![Box::new(test1)]);

test_group
}
////////// ANCHOR_END: get_example_test</code></pre>
</p>
</details>
<ol>
Expand All @@ -195,24 +234,60 @@ <h1 id="how-to-write"><a class="header" href="#how-to-write">How to write</a></h
Therefore, it is common practice here to write an OCI Runtime Spec that executes <code>runtimetest</code>.</p>
</li>
</ol>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/integration_test/src/tests/example/hello_world.rs:get_example_spec}}</code></pre>
<pre><code class="language-rust no_run noplayground">fn create_spec() -&gt; Result&lt;Spec&gt; {
SpecBuilder::default()
.process(
ProcessBuilder::default()
.args(
["runtimetest", "hello_world"]
.iter()
.map(|s| s.to_string())
.collect::&lt;Vec&lt;String&gt;&gt;(),
)
.build()?,
)
.build()
.context("failed to create spec")
}</code></pre>
<ol start="2">
<li>Prepare a function that returns a <code>TestResult</code>, which represents the result of the test.</li>
</ol>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/integration_test/src/tests/example/hello_world.rs:example_test}}</code></pre>
<pre><code class="language-rust no_run noplayground">fn example_test() -&gt; TestResult {
let spec = test_result!(create_spec());
test_inside_container(spec, &amp;|_| Ok(()))
}</code></pre>
<ol start="3">
<li>Create a <code>TestGroup</code> and register a test case you created</li>
</ol>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/integration_test/src/tests/example/hello_world.rs:get_example_test}}</code></pre>
<pre><code class="language-rust no_run noplayground">pub fn get_example_test() -&gt; TestGroup {
let mut test_group = TestGroup::new("example");
let test1 = Test::new("hello world", Box::new(example_test));
test_group.add(vec![Box::new(test1)]);

test_group
}</code></pre>
<ol start="4">
<li>Register the <code>TestGroup</code> you created to a <code>TestManager</code></li>
</ol>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/integration_test/src/main.rs:register_example_test}}</code></pre>
<pre><code class="language-rust no_run noplayground"> let mut tm = TestManager::new();
let example = get_example_test();
tm.add_test_group(Box::new(example));</code></pre>
<ol start="5">
<li>Write the validation you want to run within a test container</li>
</ol>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/runtimetest/src/main.rs:example_runtimetest_main}}</code></pre>
<pre><code class="language-rust no_run noplayground">{{#include ../../../../tests/runtimetest/src/tests.rs:example_hello_world}}</code></pre>
<pre><code class="language-rust no_run noplayground">fn main() {
let spec = get_spec();
let args: Vec&lt;String&gt; = env::args().collect();
let execute_test = match args.get(1) {
Some(execute_test) =&gt; execute_test.to_string(),
None =&gt; return eprintln!("error due to execute test name not found"),
};

match &amp;*execute_test {
"hello_world" =&gt; tests::hello_world(&amp;spec),</code></pre>
<pre><code class="language-rust no_run noplayground">pub fn hello_world(_spec: &amp;Spec) {
println!("Hello world");
}</code></pre>

</main>

Expand Down
Loading

0 comments on commit 1fb7a00

Please sign in to comment.