Skip to content
Closed
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
4 changes: 4 additions & 0 deletions .github/workflows/build_image_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with:
persist-credentials: false
- name: set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v6
with:
go-version-file: go.mod
- name: Install make
run: sudo apt -y install make
- name: build and save image
Expand Down
6 changes: 0 additions & 6 deletions .github/workflows/pull_request_e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ jobs:
steps:
- name: install make
run: sudo apt-get install make
- name: install oc & kubectl
run: |
wget https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable-4.15/openshift-client-linux.tar.gz
tar xvf openshift-client-linux.tar.gz oc kubectl
sudo cp oc kubectl /usr/local/bin
oc version
- name: set up go 1.x
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v6
with:
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ jobs:
echo "$tag is NOT a valid release tag"
exit 1
fi
- name: set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v6
with:
go-version-file: go.mod
- name: install make
run: sudo apt-get install make
# QEMU and buildx needed for multiarch builds (otherwise, microdnf step fails)
Expand All @@ -47,13 +51,13 @@ jobs:
- name: build and push manifest with images
run: MULTIARCH_TARGETS="${{ env.WF_MULTIARCH_TARGETS }}" IMAGE_ORG=${{ env.WF_ORG }} VERSION=${{ env.tag }} CLEAN_BUILD=1 make images
- name: build plugin artifact
run: IMAGE_ORG=${{ env.WF_ORG }} VERSION=${{ env.tag }} make release
run: IMAGE_ORG=${{ env.WF_ORG }} VERSION=${{ env.tag }} make release-all
- name: create draft release and upload binaries
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
tag_name: ${{ env.tag }}
name: ${{ env.tag }}
draft: true
prerelease: false
files: netobserv-cli.tar.gz
files: netobserv-cli-*.tar.gz
body: Edit to remove this content, click on 'generate release notes' above and publish. It will trigger the krew-release-bot.
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,23 @@ tmp
cover.out
kubeconfig
netobserv-cli.tar.gz
netobserv-cli-*.tar.gz
cli-e2e-img.tar
e2e/commands
e2e/output
e2e-logs
bin/

# Local OS and editor files
.DS_Store
._*
.idea/
.vscode/
*.swp
*.swo
*~

# Additional generated image and test output
/out/
/cover*.out
/test.out
66 changes: 59 additions & 7 deletions .krew.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,65 @@ spec:
collector for analysis and visualization.
platforms:
- selector:
matchExpressions:
- key: "os"
operator: "In"
values:
- darwin
- linux
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli.tar.gz" .TagName }}
matchLabels:
os: linux
arch: amd64
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli-linux-amd64.tar.gz" .TagName }}
files:
- from: "build/netobserv"
to: "netobserv"
- from: "LICENSE"
to: "."
bin: netobserv
- selector:
matchLabels:
os: linux
arch: arm64
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli-linux-arm64.tar.gz" .TagName }}
files:
- from: "build/netobserv"
to: "netobserv"
- from: "LICENSE"
to: "."
bin: netobserv
- selector:
matchLabels:
os: linux
arch: ppc64le
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli-linux-ppc64le.tar.gz" .TagName }}
files:
- from: "build/netobserv"
to: "netobserv"
- from: "LICENSE"
to: "."
bin: netobserv
- selector:
matchLabels:
os: linux
arch: s390x
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli-linux-s390x.tar.gz" .TagName }}
files:
- from: "build/netobserv"
to: "netobserv"
- from: "LICENSE"
to: "."
bin: netobserv
- selector:
matchLabels:
os: darwin
arch: amd64
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli-darwin-amd64.tar.gz" .TagName }}
files:
- from: "build/netobserv"
to: "netobserv"
- from: "LICENSE"
to: "."
bin: netobserv
- selector:
matchLabels:
os: darwin
arch: arm64
{{addURIAndSha "https://github.com/netobserv/network-observability-cli/releases/download/{{ .TagName }}/netobserv-cli-darwin-arm64.tar.gz" .TagName }}
files:
- from: "build/netobserv"
to: "netobserv"
Expand Down
28 changes: 17 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# We do not use --platform feature to auto fill this ARG because of incompatibility between podman and docker
ARG TARGETARCH=amd64

# Build the manager binary
FROM docker.io/library/golang:1.26 AS builder
# Build the collector and standalone Go plugin
# Match the target platform so the collector retains SQLite CGO support.
FROM --platform=linux/$TARGETARCH docker.io/library/golang:1.26 AS builder

ARG TARGETARCH
ARG LDFLAGS
ARG VERSION=main
ARG COLLECTOR_IMAGE=quay.io/netobserv/network-observability-cli:${VERSION}
ARG AGENT_IMAGE=quay.io/netobserv/netobserv-ebpf-agent:main
ARG PULL_POLICY=Always

WORKDIR /opt/app-root

Expand All @@ -19,18 +24,16 @@ COPY vendor/ vendor/
# Build collector
RUN GOARCH=$TARGETARCH go build -ldflags "$LDFLAGS" -mod vendor -a -o build/network-observability-cli

# We still need Makefile & resources for oc-commands; copy them after go build for caching
COPY commands/ commands/
# Build the native plugin through the shared Makefile target.
COPY res/ res/
COPY scripts/ scripts/
COPY Makefile Makefile
COPY .mk/ .mk/

# Embed commands in case users want to pull it from collector image
RUN USER=netobserv VERSION=main make oc-commands
RUN make oc-commands GOARCH=$TARGETARCH PLUGIN_GOOS=linux \
VERSION="$VERSION" IMAGE="$COLLECTOR_IMAGE" AGENT_IMAGE="$AGENT_IMAGE" \
PULL_POLICY="$PULL_POLICY"

# Prepare output dir
RUN mkdir -p output
RUN mkdir -p output && chmod 0775 output

# Create final image from ubi + built binary and command
FROM --platform=linux/$TARGETARCH registry.access.redhat.com/ubi9/ubi-minimal:1789639833
Expand All @@ -40,8 +43,11 @@ RUN microdnf install -y tar && \

WORKDIR /

COPY --from=builder /opt/app-root/build .
COPY --from=builder --chown=65532:65532 /opt/app-root/output /output
COPY --from=builder /opt/app-root/build/network-observability-cli /network-observability-cli
COPY --from=builder /opt/app-root/build/oc-netobserv /oc-netobserv
# OpenShift runs containers with an arbitrary UID in group 0.
COPY --from=builder --chown=65532:0 /opt/app-root/output /output
RUN chmod 0775 /output
USER 65532:65532

ENTRYPOINT ["/network-observability-cli"]
54 changes: 26 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
VERSION ?= main

# Go architecture and targets images to build
GOARCH ?= amd64
GOARCH ?= $(shell go env GOARCH)
PLUGIN_GOOS ?= $(shell go env GOOS)
MULTIARCH_TARGETS ?= amd64

# In CI, to be replaced by `netobserv`
Expand All @@ -22,9 +23,8 @@ OUTPUT := $(DIST_DIR)/$(NAME)
COMMANDS = flows packets cleanup
COMMAND_ARGS ?=

# Get either oc (favorite) or kubectl paths
K8S_CLI_BIN_PATH = $(shell which oc 2>/dev/null || which kubectl)
K8S_CLI_BIN ?= $(shell basename ${K8S_CLI_BIN_PATH})
# Plugin filename prefix; neither external CLI is needed to build or run it.
K8S_CLI_BIN ?= oc

# Image registry such as quay or docker
IMAGE_REGISTRY ?= quay.io
Expand All @@ -40,8 +40,8 @@ PULL_POLICY ?=Always
AGENT_IMAGE ?= $(IMAGE_REGISTRY)/netobserv/netobserv-ebpf-agent:main

# Image building tool (docker / podman) - docker is preferred in CI
OCI_BIN_PATH := $(shell which docker 2>/dev/null || which podman)
OCI_BIN ?= $(shell basename ${OCI_BIN_PATH})
OCI_BIN_PATH = $(shell command -v docker 2>/dev/null || command -v podman 2>/dev/null)
OCI_BIN ?= $(if $(OCI_BIN_PATH),$(notdir $(OCI_BIN_PATH)),podman)
OCI_BUILD_OPTS ?=
KREW_PLUGIN ?=false

Expand All @@ -57,13 +57,12 @@ ifneq ($(CLEAN_BUILD),)
endif

GOLANGCI_LINT_VERSION = v2.12.2
BASH_VERSION = v4.2.0
YQ_VERSION = v4.45.1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need YQ ? We should handle everything in golang


# build a single arch target provided as argument
define build_target
echo 'building image for arch $(1)'; \
DOCKER_BUILDKIT=1 $(OCI_BIN) buildx build --load --build-arg LDFLAGS="${LDFLAGS}" --build-arg TARGETARCH=$(1) ${OCI_BUILD_OPTS} ${EXTRA_BUILD_FLAGS} -t ${IMAGE}-$(1) -f Dockerfile .;
DOCKER_BUILDKIT=1 $(OCI_BIN) buildx build --load --build-arg LDFLAGS="${LDFLAGS}" --build-arg TARGETARCH=$(1) --build-arg VERSION="$(VERSION)" --build-arg COLLECTOR_IMAGE="$(IMAGE)" --build-arg AGENT_IMAGE="$(AGENT_IMAGE)" --build-arg PULL_POLICY="$(PULL_POLICY)" ${OCI_BUILD_OPTS} ${EXTRA_BUILD_FLAGS} -t ${IMAGE}-$(1) -f Dockerfile .;
endef

# push a single arch target image
Expand Down Expand Up @@ -119,13 +118,13 @@ tests-e2e: oc-commands ## Run e2e tests using kind cluster
@rm -rf e2e/output
@rm -f cli-e2e-img.tar
go clean -testcache
$(OCI_BIN) build . -t ${IMAGE}
$(OCI_BIN) build --build-arg TARGETARCH=$(GOARCH) --build-arg VERSION="$(VERSION)" --build-arg COLLECTOR_IMAGE="$(IMAGE)" --build-arg AGENT_IMAGE="$(AGENT_IMAGE)" --build-arg PULL_POLICY="$(PULL_POLICY)" . -t ${IMAGE}
$(OCI_BIN) save -o cli-e2e-img.tar ${IMAGE}
GOOS=$(GOOS) go test -p 1 -timeout 30m -v -mod vendor -tags e2e ./e2e/...

.PHONY: tests-int
tests-int: ## Run e2e integration tests. You need a running cluster connected
GOOS= go test -p 1 -timeout 30m -v -mod vendor ./e2e/integration-tests/...
tests-int: oc-commands ## Build the Go plugin and run integration tests against KUBECONFIG
PATH="$(abspath $(DIST_DIR)):$$PATH" GOOS= go test -p 1 -timeout 30m -v -mod vendor ./e2e/integration-tests/...

.PHONY: coverage-report
coverage-report: ## Generate coverage report
Expand Down Expand Up @@ -159,18 +158,12 @@ clean: ## Clean up build directory
@rm -rf $(FILES_OUTPUT_DIR)

.PHONY: commands
commands: ## Generate either oc or kubectl plugins and add them to build folder
@echo "### Generating $(K8S_CLI_BIN) commands"
DIST_DIR=$(DIST_DIR) \
K8S_CLI_BIN=$(K8S_CLI_BIN) \
IMAGE=$(IMAGE) \
PULL_POLICY=$(PULL_POLICY) \
AGENT_IMAGE=$(AGENT_IMAGE) \
VERSION=$(VERSION) \
REQUIRED_BASH_VERSION=$(BASH_VERSION) \
REQUIRED_YQ_VERSION=$(YQ_VERSION) \
SUPPORTED_ARCHS=$(MULTIARCH_TARGETS) \
./scripts/inject.sh
commands: ## Build the standalone Go plugin (also usable through oc/kubectl)
@mkdir -p $(DIST_DIR)
CGO_ENABLED=0 GOOS=$(PLUGIN_GOOS) GOARCH=$(GOARCH) go build -mod=vendor \
-ldflags "-X main.version=$(VERSION) -X github.com/netobserv/network-observability-cli/internal/pkg/plugin.CollectorImage=$(IMAGE) -X github.com/netobserv/network-observability-cli/internal/pkg/plugin.AgentImage=$(AGENT_IMAGE) -X github.com/netobserv/network-observability-cli/internal/pkg/plugin.PullPolicy=$(PULL_POLICY)" \
-o $(DIST_DIR)/$(if $(filter true,$(KREW_PLUGIN)),,$(K8S_CLI_BIN)-)netobserv.tmp ./cmd/oc-netobserv
mv $(DIST_DIR)/$(if $(filter true,$(KREW_PLUGIN)),,$(K8S_CLI_BIN)-)netobserv.tmp $(DIST_DIR)/$(if $(filter true,$(KREW_PLUGIN)),,$(K8S_CLI_BIN)-)netobserv

.PHONY: kubectl-commands
kubectl-commands: K8S_CLI_BIN=kubectl
Expand All @@ -186,26 +179,31 @@ install-commands: commands ## Generate plugins and add them to /usr/bin/

.PHONY: docs
docs: oc-commands ## Generate asciidoc
./scripts/generate-doc.sh
CLI_BIN="./$(DIST_DIR)/oc-netobserv" ./scripts/generate-doc.sh

.PHONY: update-config
update-config: ## Update config from operator repo
./scripts/update-config.sh

.PHONY: release
release: clean ## Generate tar.gz containing krew plugin
release: ## Build an OS/architecture-specific Krew archive
$(MAKE) KREW_PLUGIN=true kubectl-commands
tar -czf netobserv-cli.tar.gz LICENSE ./build/netobserv
tar -czf netobserv-cli-$(PLUGIN_GOOS)-$(GOARCH).tar.gz LICENSE ./build/netobserv

.PHONY: release-all
release-all: ## Build supported Linux and macOS plugin archives
@for arch in amd64 arm64 ppc64le s390x; do $(MAKE) release PLUGIN_GOOS=linux GOARCH=$$arch || exit $$?; done
@for arch in amd64 arm64; do $(MAKE) release PLUGIN_GOOS=darwin GOARCH=$$arch || exit $$?; done

.PHONY: create-kind-cluster
create-kind-cluster: prereqs ## Create a kind cluster
scripts/kind-cluster.sh

.PHONY: destroy-kind-cluster
destroy-kind-cluster: KUBECONFIG=./kubeconfig
destroy-kind-cluster: ## Destroy the kind cluster.
destroy-kind-cluster: oc-commands ## Destroy the kind cluster.
test -s ./kubeconfig || { echo "kubeconfig does not exist! Exiting..."; exit 1; }
$(K8S_CLI_BIN) delete -f ./res/namespace.yml --ignore-not-found
./$(DIST_DIR)/oc-netobserv cleanup --kubeconfig="$(KUBECONFIG)"
kind delete cluster --name netobserv-cli-cluster
rm ./kubeconfig

Expand Down
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,40 @@ On Openshift environments, you can also capture metrics in your monitoring stack

To run this CLI, you will need:
- A running kubernetes / OpenShift cluster
- either `oc` or `kubectl` command installed and connected to your cluster
- A kubeconfig with valid cluster credentials (`KUBECONFIG` or `~/.kube/config`)
- Cluster admin rights

## Standalone Go CLI

`oc-netobserv` is a native Go executable. Running it directly does not require
`oc`, `kubectl`, Bash, or `yq` on your machine. It uses the Kubernetes Go client
libraries and your kubeconfig. If your kubeconfig uses an external credential
plugin, that credential plugin must still be available.

Build and run it with Go (the version in `go.mod`):

```sh
make oc-commands
./build/oc-netobserv flows --protocol=TCP --port=8080
./build/oc-netobserv packets --port=443 --background
./build/oc-netobserv follow
./build/oc-netobserv copy
./build/oc-netobserv cleanup
```

Existing commands, capture flags, `or` filter groups, image overrides, and
`NETOBSERV_NAMESPACE` remain supported. Optional `--kubeconfig`, `--context`,
`--namespace`, and `--output-dir` arguments can be supplied after the command.
Use the same connection and namespace arguments for follow-up commands.
`--yaml` generates manifests without contacting the cluster, unless
`--get-subnets` explicitly requests cluster network information.

`make kubectl-commands` builds the same executable as `kubectl-netobserv`.
Installing either binary on `PATH` also allows the existing `oc netobserv` or
`kubectl netobserv` invocation when those tools are installed.
Release archives are specific to the OS and architecture; `make release-all`
builds Linux amd64/arm64/ppc64le/s390x and macOS amd64/arm64 artifacts.

## Getting started with Krew

The CLI is available as a [Krew](https://krew.sigs.k8s.io/) plugin, which is the fastest way to get it up and running if you already use Krew.
Expand Down
Loading
Loading