Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changes/unreleased/Added-20260703-161640.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kind: Added
body: Basic demos for the `get` and `diff` functions have being created.
time: 2026-07-03T16:16:40.833460189+01:00
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ nohup.out
zig-out/
.zig-cache/
zig-pkg/
docs/
358 changes: 358 additions & 0 deletions docs/demo/demo_diff.cast

Large diffs are not rendered by default.

822 changes: 822 additions & 0 deletions docs/demo/demo_get.cast

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions docs/demo/diff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# diff Demo

The diff demo is a bit more complex, but carries more power.
For the demo a preconfigured kind cluster will be used as this works best with a installed application.
The application that will be used is [kuadrant](https://kuadrant.io).
What the application does, or how it is set up has little affect on the demo.
But what it will show is all the resources that are created and updated when using applictions.

[![asciicast](https://asciinema.org/a/lGJb04MO90oLxpCo.svg)](https://asciinema.org/a/lGJb04MO90oLxpCo)

1. Setting up the kind cluster.
In the main operator for kuadrant, the [kuadrant-operator](https://github.com/kuadrant/kuadrant-operator), there is a make target that can be used to set up a dev cluster.
For what we need to do this is good enough for us.
Follow their guide on getting the local set create.
Hint: `make local-setup`

2. Take an initial dump of the resources on the cluster, and save them to the database.
```
kubectlgetall get --all-namespaces --output sqlite --database diff_demo.db --label initial
```

3. Apply the resource in the `diff_demo` directory.
This applies three resources to the cluster, kuadrant CR, RateLimitPolicy, and HTTProute.
We will see afterwards all the resources changed by adding these resources.
```
kubectl apply -k diff_demo
```

4. Wait for the RateLimitPolicy to become "Enforced".
Again what this is doing does not matter for the demo, but we do want to capture all the resources that may have changed.
```
kubectl wait ratelimitpolicy/httpbin-ratelimit --for=condition=Enforced --timeout=300s
```
5. Take a new dump from the cluster once the resources have being applied.
Setting a new label
```
kubectlgetall get --all-namespaces --output sqlite --database diff_demo.db --label resources_added
```

6. Final the `diff` command can be used to compare the resources from the `initial` label, and the `resources_added` label.
As events can be noisy below we filter those out.
```
kubectlgetall diff --database diff_demo.db initial resources_added --exclude event
```

## Other outputs
Like the other commands the output can be configured to output in JSON using the `--output` flag.
Unlike the `get` command the output type can not be `sqlite`.
That type does not make sense currently for this command.

15 changes: 15 additions & 0 deletions docs/demo/diff_demo/httproute.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin-route
spec:
parentRefs:
- name: kuadrant-ingressgateway
namespace: gateway-system
hostnames:
- "httpbin.local"
rules:
- backendRefs:
- name: httpbin
port: 80
6 changes: 6 additions & 0 deletions docs/demo/diff_demo/kuadrant.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
apiVersion: kuadrant.io/v1beta1
kind: Kuadrant
metadata:
name: kuadrant-sample
spec: {}
4 changes: 4 additions & 0 deletions docs/demo/diff_demo/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resources:
- kuadrant.yaml
- httproute.yaml
- ratelimitpolicy.yaml
15 changes: 15 additions & 0 deletions docs/demo/diff_demo/ratelimitpolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: kuadrant.io/v1
kind: RateLimitPolicy
metadata:
name: httpbin-ratelimit
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: httpbin-route
limits:
"general-user":
rates:
- limit: 5
window: 10s
64 changes: 64 additions & 0 deletions docs/demo/get.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Get Demo

This shows how to get a list of all the resources from a cluster using `kubectlgetall get`.
A KinD cluster is used in for the demo.

[![asciicast](https://asciinema.org/a/1260080.svg)](https://asciinema.org/a/1260080)

## Simple examples
1. Create the cluster. This creates a very basic cluster.
```sh
kind create cluster
```

2. List all the resources from the cluster.
```sh
kubectlgetall get --all-namespaces
```
This will return a long list of resources on the cluster group by type.
By default, this is not a sorted list, but can be sorted by adding the `--sort` flag.

3. List resources from a specified namespace.
```sh
kubectlgetall get --namespace kube-system
```

4. List resources from the namespace your kubeconfig defaults too.
```sh
kubectlgetall get
```

## Output types
There are three formats the `get` command can output, TTY, JSON, or SQLite.
TTY is the default output that show the tables, and is the output type format used in the simple examples.

1. The JSON output gives all the data as a JSON object.
```sh
kubectlgetall get --output json
```
2. The output is not pretty printed, but this can be done by piping the results into `jq`.
```sh
kubectlgetall get --output json | jq
```

3. The next output type is SQLite.
This is more complex, but allows creating historical views of a cluster.
When the output is set to `sqlite`, the path to a SQLite database most also be given.
If the database does not exist, it will be created.
```sh
kubectlgetall get --output sqlite --database example.db
```
If everything works as expected by default there will be no output to the terminal.

4. While saving the results to the database is useful, it is much better to include a label on the entries.
When the label is added this can be used to look results from multiple runs at a later date.
```sh
kubectlgetall get --output sqlite --database example.db --label demo1
```

## Other Options
There are other options that can be set on the `get` function, such as the log level.
These options can be viewed by passing the `--help` flag.
```sh
kubectlgetall get --help
```
49 changes: 7 additions & 42 deletions src/get.zig
Original file line number Diff line number Diff line change
Expand Up @@ -27,58 +27,23 @@ pub fn getMain(io: std.Io, gpa: std.mem.Allocator, iter: *std.process.Args.Itera
};
defer res.deinit();

var namespace: []const u8 = &[_]u8{};
var allNamespaces = false;
var sort = false;
var output = types.Output.tty;
var database: []const u8 = &[_]u8{};
var label: []const u8 = &[_]u8{};
var exclude: ?[]const []const u8 = null;

if (res.args.help != 0) {
try help.get(io, .stdout());
std.process.exit(0);
}

if (res.args.namespace) |n| {
namespace = n;
}

if (res.args.@"all-namespaces" == 1) {
allNamespaces = true;
}

if (res.args.sort == 1) {
sort = true;
}

if (res.args.output) |o| {
output = o;
}

if (res.args.database) |d| {
database = d;
}

if (res.args.label) |l| {
label = l;
}

if (res.args.@"log-level") |l| {
logging.setLogLevel(l);
}

if (res.args.exclude.len > 0) {
exclude = res.args.exclude;
}
const config = types.Config{
.namespace = namespace,
.all = allNamespaces,
.sort = sort,
.exclude = exclude,
.output = output,
.database = database,
.label = label,
.namespace = if (res.args.namespace) |v| v else "",
.all = (res.args.@"all-namespaces" == 1),
.sort = (res.args.sort == 1),
.exclude = if (res.args.exclude.len > 0) res.args.exclude else null,
.output = if (res.args.output) |v| v else .tty,
.database = if (res.args.database) |v| v else "",
.label = if (res.args.label) |v| v else "",
.timestamp = std.Io.Timestamp.now(io, .real).toSeconds(),
};

Expand Down
11 changes: 5 additions & 6 deletions src/snapshot.zig
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,14 @@ pub fn cmd(io: std.Io, gpa: std.mem.Allocator, iter: *std.process.Args.Iterator)
.database = res.args.database orelse return error.MissingDatabase,
.label = res.args.label orelse return error.MissingLabel,
.exclude = if (res.args.exclude.len > 0) res.args.exclude else null,
.all = if (res.args.@"all-namespaces" == 1) true else false,
.all = (res.args.@"all-namespaces" == 1),
.namespace = if (res.args.namespace) |n| n else "",
.startTime = std.Io.Timestamp.now(io, .real).toSeconds(),
.delay = if (res.args.delay) |v| @intCast(v) else types.DefaultDelay,
.limit = if (res.args.limit) |v| @intCast(v) else 0,
.count = if (res.args.count) |v| v else 0,
};

if (res.args.delay) |v| config.delay = @intCast(v);
if (res.args.limit) |v| config.limit = @intCast(v);
if (res.args.count) |v| config.count = v;

std.log.debug("{f}", .{config});

try db.init(config.database);
Expand Down Expand Up @@ -88,7 +87,6 @@ pub fn cmd(io: std.Io, gpa: std.mem.Allocator, iter: *std.process.Args.Iterator)
},
else => return err,
};
defer resource.deinit(gpa);

if (resource.items.len > 0) {
if (utils.matchedExclude(config.exclude, resource.items[0].kind)) |matched| {
Expand All @@ -97,6 +95,7 @@ pub fn cmd(io: std.Io, gpa: std.mem.Allocator, iter: *std.process.Args.Iterator)
continue;
}
}
defer resource.deinit(gpa);

try db.add(resource, label, timestamp);
}
Expand Down
4 changes: 3 additions & 1 deletion src/types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const std = @import("std");
pub const Output = enum { tty, json, sqlite };
pub const Bool = enum { true, false };

pub const DefaultDelay: i64 = 60;

pub const Config = struct {
namespace: []const u8,
all: bool,
Expand Down Expand Up @@ -73,7 +75,7 @@ pub const SnapshotConfig = struct {
exclude: ?[]const []const u8 = null,
count: u64 = 0,
limit: i64 = 0,
delay: i64 = 60,
delay: i64 = DefaultDelay,
namespace: []const u8,
all: bool,
startTime: i64,
Expand Down
Loading