Skip to content
Open
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 .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
# and editors capable of LF line endings.
*.go text eol=lf diff=golang

# Images should be stored in Git LFS, and not have their line endings modified.
*.gif filter=lfs diff=lfs merge=lfs -text

# Generated files — collapsed in PR diffs, excluded from language stats.
api/**/zz_generated.deepcopy.go linguist-generated
charts/network-operator/templates/** linguist-generated
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ make undeploy-crds
make undeploy
```

## kubectl Plugin

The `kubectl-net` plugin extends kubectl with shorthand flags and resource lifecycle operations tailored to network-operator.

```bash
kubectl net get interfaces --device leaf1
kubectl net pause devices leaf1 --recursive
```

See [kubectl-net/README.md](kubectl-net/README.md) for installation and full usage documentation.

## Project Distribution

Following are the steps to build the installer and distribute this project to users.
Expand Down
24 changes: 24 additions & 0 deletions kubectl-net/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin/*

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Go workspace file
go.work
go.work.sum

# editor and IDE paraphernalia
.idea
.vscode
*.swp
*.swo
*~
111 changes: 111 additions & 0 deletions kubectl-net/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<!--
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and IronCore contributors
# SPDX-License-Identifier: Apache-2.0
-->

# kubectl-net

A [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/) for managing [network-operator](https://github.com/ironcore-dev/network-operator) custom resources.

## Installation

Install via `go install`:

```bash
go install github.com/ironcore-dev/network-operator/kubectl-net/cmd@latest
```

> Ensure your `$GOBIN` (or default `$GOPATH/bin`) is on your `$PATH`.

Verify kubectl discovers the plugin:

```bash
kubectl plugin list | grep kubectl-net
```

You can now run the plugin as `kubectl net`.

<details>
<summary>Build from source</summary>

```bash
go build -o kubectl-net ./cmd/kubectl-net.go
sudo install -m 0755 kubectl-net /usr/local/bin/kubectl-net
kubectl plugin list | grep kubectl-net
```

</details>

## Usage

![demo](examples/demo.gif)

### Get resources

The `get` subcommand works like `kubectl get` and supports the same output flags (`-o yaml`, `-o json`, `-o wide`, `-o name`, `-o jsonpath=...`, etc.).

```bash
# List all devices (server-side table output, same as kubectl get)
kubectl net get devices

# Get a single device
kubectl net get devices leaf1

# Filter interfaces by device
kubectl net get interfaces --device leaf1

# Filter interfaces by VRF
kubectl net get interfaces --vrf default

# Filter interfaces by aggregate
kubectl net get interfaces --aggregate ae0

# Filter VLANs by EVPN instance
kubectl net get vlans --evi evi-100

# Filter VLANs by routed VLAN interface
kubectl net get vlans --routed-vlan irb100

# Output as YAML
kubectl net get devices leaf1 -o yaml
```

### Pause and unpause resources

The `pause` and `unpause` subcommands set or remove the `networking.metal.ironcore.dev/paused` annotation. For devices, `--recursive` also sets `spec.paused` to propagate to child resources.

```bash
# Pause a single interface
kubectl net pause interfaces lo0

# Unpause interface
kubectl net unpause interfaces lo0

# Pause a device and all child resources
kubectl net pause devices leaf1 --recursive

# Unpause a device and all child resources
kubectl net unpause devices leaf1 --recursive

# Pause all interfaces on a device
kubectl net pause interfaces --device leaf1
```

### Shell completion

```bash
# Generate and source completion for your shell
source <(kubectl net completion bash)
source <(kubectl net completion zsh)
kubectl net completion fish | source
```

## Label shorthand flags

| Flag | Label | Available for |
| ---------------- | ------------------------------------------- | ------------- |
| `--device`, `-d` | `networking.metal.ironcore.dev/device-name` | All resources |
| `--aggregate` | `networking.metal.ironcore.dev/aggregate` | Interfaces |
| `--vrf` | `networking.metal.ironcore.dev/vrf` | Interfaces |
| `--routed-vlan` | `networking.metal.ironcore.dev/routed-vlan` | VLANs |
| `--evi` | `networking.metal.ironcore.dev/l2vni` | VLANs |
23 changes: 23 additions & 0 deletions kubectl-net/cmd/kubectl-net.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

package main

import (
"os"

"github.com/spf13/pflag"
"k8s.io/cli-runtime/pkg/genericiooptions"

"github.com/ironcore-dev/kubectl-net/pkg/cmd"
)

func main() {
flags := pflag.NewFlagSet("kubectl-net", pflag.ExitOnError)
pflag.CommandLine = flags

root := cmd.NewCmdNet(genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr})
if err := root.Execute(); err != nil {
os.Exit(1)
}
}
3 changes: 3 additions & 0 deletions kubectl-net/examples/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions kubectl-net/examples/demo.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: 2026 SAP SE or an SAP affiliate company and IronCore contributors
# SPDX-License-Identifier: Apache-2.0

Require kubectl
Require jq

Output examples/demo.gif

Set Shell "bash"
Set Padding 24

Type "# List all devices (drop-in replacement for kubectl get)" Enter Sleep 1s
Type "kubectl net get devices" Enter Sleep 3s

Type "# Filter interfaces by device name" Enter Sleep 1s
Type "kubectl net get interfaces --device leaf1" Enter Sleep 3s

Type "clear" Sleep 1s Enter Sleep 500ms

Type "# Pause a single interface" Enter Sleep 1s
Type "kubectl net pause interfaces lo0" Enter Sleep 3s

Type "# Unpause the interface" Enter Sleep 1s
Type "kubectl net unpause interfaces lo0" Enter Sleep 3s

Type "clear" Sleep 1s Enter Sleep 500ms

Type "# Recursively pause a device and children" Enter Sleep 1s
Type "kubectl net pause devices leaf1 --recursive" Enter Sleep 3s

Type "# Verify the device is paused" Enter Sleep 1s
Type "kubectl net get devices leaf1 -o yaml | yq .spec.paused" Enter Sleep 3s

Type "# Unpause the device and children" Enter Sleep 1s
Type "kubectl net unpause devices leaf1 --recursive" Enter Sleep 3s
75 changes: 75 additions & 0 deletions kubectl-net/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
module github.com/ironcore-dev/kubectl-net

go 1.26.0

require (
github.com/ironcore-dev/network-operator v0.0.0
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
k8s.io/apimachinery v0.36.0
k8s.io/cli-runtime v0.35.2
k8s.io/client-go v0.36.0
)

require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-openapi/jsonpointer v0.22.4 // indirect
github.com/go-openapi/jsonreference v0.21.4 // indirect
github.com/go-openapi/swag v0.25.4 // indirect
github.com/go-openapi/swag/cmdutils v0.25.4 // indirect
github.com/go-openapi/swag/conv v0.25.4 // indirect
github.com/go-openapi/swag/fileutils v0.25.4 // indirect
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
github.com/go-openapi/swag/loading v0.25.4 // indirect
github.com/go-openapi/swag/mangling v0.25.4 // indirect
github.com/go-openapi/swag/netutils v0.25.4 // indirect
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/net v0.56.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.21.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.38.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/api v0.36.0 // indirect
k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/kustomize/api v0.20.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)

replace github.com/ironcore-dev/network-operator => ..
Loading
Loading