Skip to content
Draft
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
125 changes: 125 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Retina - eBPF Network Observability Platform

Retina is a cloud-agnostic, open-source Kubernetes network observability platform that provides centralized monitoring for application health, network health, and security. Built with Go, eBPF, and container technologies for Linux and Windows environments.

Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.

## Working Effectively

### Environment Setup
- Install required dependencies:
- `sudo apt update && sudo apt install -y clang llvm-strip-18 jq`
- `sudo ln -sf /usr/bin/llvm-strip-18 /usr/bin/llvm-strip` (if needed)
- Go 1.24.6+ required (check with `go version`)
- Docker and Helm required for container operations
- `clang` and `llvm-strip` are CRITICAL for eBPF compilation

### Core Build Commands
- `make retina` -- builds retina binary -- takes ~1 minute (includes eBPF generation). NEVER CANCEL. Set timeout to 10+ minutes.
- `make retina-capture-workload` -- builds capture workload binary -- takes ~2 seconds
- CLI: `cd cli && go build -o ../output/linux_amd64/retina/kubectl-retina .` -- takes ~6 seconds
- `make clean` -- clean build artifacts -- takes < 1 second

### Testing and Validation
- `make test` -- runs full test suite -- takes 10+ minutes. NEVER CANCEL. Set timeout to 20+ minutes.
- Basic package tests: `go test -timeout 10m -tags=unit ./pkg/...` -- takes ~6 minutes with some expected failures in cross-platform code
- `make fmt` -- format code -- takes ~1 second
- `make lint` -- runs linting -- takes ~2-3 minutes. May show some issues in generated mock files that can be ignored.

### BPF Generation and Plugins
- BPF generation for current architecture works: generates `.o` and `.go` files for eBPF programs
- Cross-compilation (ARM64) may fail in development environment - this is expected
- Plugin test example: `cd test/plugin && make test-packetforward` -- builds and runs plugin tests with sudo
- Individual plugins can be tested but require network traffic to show meaningful data

## Validation Scenarios

### Basic Functionality Validation
Always test these core workflows after making changes:

1. **Build and run agent**:
```bash
make retina
./output/linux_amd64/retina/retina --help
```

2. **Build and test CLI**:
```bash
cd cli && go build -o ../output/linux_amd64/retina/kubectl-retina .
./output/linux_amd64/retina/kubectl-retina --help
./output/linux_amd64/retina/kubectl-retina version
```

3. **Test plugin functionality**:
```bash
cd test/plugin && make test-packetforward
# This will run until Ctrl+C - expect to see "Start collecting packet forward metrics"
```

## Critical Build Timing and Warnings

### NEVER CANCEL - Build Time Expectations
- **Main binary build (`make retina`)**: Takes 1-2 minutes including eBPF generation. NEVER CANCEL. Use timeout 10+ minutes.
- **Full test suite (`make test`)**: Takes 10-15 minutes. NEVER CANCEL. Use timeout 20+ minutes.
- **Linting (`make lint`)**: Takes 2-3 minutes. NEVER CANCEL. Use timeout 5+ minutes.
- **Plugin tests**: Can run indefinitely waiting for network traffic - this is expected behavior.

### Expected Build Issues
- Cross-compilation for ARM64 may fail with "exec format error" - this is expected in development environment
- Some unit tests fail due to missing kubebuilder/etcd dependencies - this is expected
- Lint warnings about generated mock files are expected and can be ignored
- BPF compilation warnings about operator precedence are expected and harmless

## Project Structure

### Key Directories
- `/pkg/plugin/` - eBPF plugins for network observability (conntrack, dropreason, packetforward, etc.)
- `/controller/` - Main retina agent controller code
- `/cli/` - kubectl-retina CLI implementation
- `/captureworkload/` - Network capture workload implementation
- `/operator/` - Kubernetes operator code
- `/test/plugin/` - Individual plugin test utilities
- `/docs/08-Contributing/02-development.md` - Detailed development guide

### Important Files
- `Makefile` - Primary build system with comprehensive targets
- `go.mod` - Go 1.24.6, extensive Kubernetes and eBPF dependencies
- `.devcontainer/` - GitHub Codespaces configuration with required tools
- `.github/workflows/` - CI/CD pipelines for testing and building

## Common Development Tasks

### Before Committing Changes
Always run these commands before pushing:
1. `make fmt` - Format code (required for CI)
2. `make lint` - Check code quality (may show expected warnings)
3. `make retina` - Ensure main binary builds correctly
4. Test CLI: `cd cli && go build .` - Ensure CLI builds

### Working with eBPF Code
- eBPF source files are in `pkg/plugin/*/\_cprog/` directories
- Generated files: `*_bpfel_x86.o` and `*_bpfel_x86.go`
- BPF generation happens automatically during build
- Some compiler warnings about operator precedence are expected and harmless

### Container and Helm Operations
- `make retina-image` - Build container image (requires registry access)
- Images are published to GHCR (GitHub Container Registry)
- Helm charts are available in the repository for deployment
- Full deployment requires Kubernetes cluster with appropriate permissions

## Debugging and Troubleshooting

### Common Issues
- **"exec format error"**: Usually cross-compilation issue, rebuild for current arch
- **Missing kubebuilder**: Some tests require Kubernetes test environment
- **Plugin tests hanging**: Normal behavior - plugins wait for network traffic
- **Lint failures**: Check if they're in generated mock files (can be ignored)
- **BPF compilation warnings**: Expected and generally harmless

### Log Analysis
- Agent logs provide detailed eBPF and networking information
- CLI operations are verbose and show capture job creation details
- Plugin tests show real-time network metrics when traffic is available

This is a complex, enterprise-grade networking platform. Take time to understand the eBPF integration and Kubernetes-native architecture before making changes.
4 changes: 2 additions & 2 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ type Config struct {
}

var Retina = &cobra.Command{
Use: "kubectl-retina",
Use: "kubectl-retina",
Short: "A kubectl plugin for Retina",
Long: "A kubectl plugin for Retina\nRetina is an eBPF distributed networking observability tool for Kubernetes.",
Long: "A kubectl plugin for Retina\nRetina is an eBPF distributed networking observability tool for Kubernetes.",
PersistentPreRun: func(*cobra.Command, []string) {
var config Config
file, _ := os.ReadFile(ClientConfigPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
func TestOverwriteDashboards(t *testing.T) {
// get all json's in various generation deploly folders
files, err := filepath.Glob("../../../grafana-dashboards/*.json")

if err != nil {
t.Fatal(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
func TestDashboardsAreSimplified(t *testing.T) {
// get all json's in this folder
files, err := filepath.Glob("../../../grafana-dashboards/*.json")

if err != nil {
t.Fatal(err)
}
Expand Down
Binary file added init/retina/retina
Binary file not shown.
3 changes: 1 addition & 2 deletions operator/cilium-crds/k8s/fakeresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import (
"github.com/cilium/cilium/pkg/k8s/resource"
)

type fakeresource[T k8sRuntime.Object] struct {
}
type fakeresource[T k8sRuntime.Object] struct{}

func (f *fakeresource[T]) Events(ctx context.Context, opts ...resource.EventsOpt) <-chan resource.Event[T] {
return make(<-chan resource.Event[T])
Expand Down
5 changes: 5 additions & 0 deletions pkg/hubble/common/mocks/mock_types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions pkg/k8s/watcher_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ func init() {
}
}

var (
logger = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s-watcher")
)
var logger = logging.DefaultLogger.WithField(logfields.LogSubsys, "k8s-watcher")

func Start(ctx context.Context, k *watchers.K8sWatcher) {
logger.Info("Starting Kubernetes watcher")
Expand Down
28 changes: 28 additions & 0 deletions pkg/log/test.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{"level":"info","ts":"2025-09-19T22:08:35.013Z","caller":"log/zap_test.go:29","msg":"test","i":0}
{"level":"info","ts":"2025-09-19T22:08:35.013Z","caller":"log/zap_test.go:29","msg":"test","i":1}
{"level":"info","ts":"2025-09-19T22:08:35.013Z","caller":"log/zap_test.go:29","msg":"test","i":2}
{"level":"info","ts":"2025-09-19T22:08:35.013Z","caller":"log/zap_test.go:29","msg":"test","i":3}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:29","msg":"test","i":4}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:29","msg":"test","i":5}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:29","msg":"test","i":6}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:29","msg":"test","i":7}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:29","msg":"test","i":8}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:29","msg":"test","i":9}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log","name":"log"}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log/test.log","name":"test.log"}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log/zap.go","name":"zap.go"}
{"level":"info","ts":"2025-09-19T22:08:35.014Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log/zap_test.go","name":"zap_test.go"}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":0}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":1}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":2}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":3}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":4}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":5}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":6}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":7}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":8}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:29","msg":"test","i":9}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log","name":"log"}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log/test.log","name":"test.log"}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log/zap.go","name":"zap.go"}
{"level":"info","ts":"2025-09-19T22:19:00.419Z","caller":"log/zap_test.go:43","msg":"Filename: ","path":"/home/runner/work/retina/retina/pkg/log/zap_test.go","name":"zap_test.go"}
4 changes: 1 addition & 3 deletions pkg/plugin/ciliumeventobserver/parser_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ import (
"go.uber.org/zap"
)

var (
ErrEmptyData = errors.New("empty data")
)
var ErrEmptyData = errors.New("empty data")

func (p *parser) Init() error {
parser, err := hp.New(slog.Default().With("cilium", "parser"),
Expand Down
Binary file modified pkg/plugin/conntrack/conntrack_bpfel_x86.o
Binary file not shown.
Binary file modified pkg/plugin/dropreason/kprobe_bpfel_x86.o
Binary file not shown.
172 changes: 172 additions & 0 deletions pkg/plugin/dropreason/mocks/mock_types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/plugin/filter/filter_bpfel_x86.o
Binary file not shown.
Loading