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
8 changes: 2 additions & 6 deletions .claude/rules/api-types.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
---
paths:
- "api/**"
---

# API Types Rules

- After modifying `api/v2/checluster_types.go`, always run `build/scripts/docker-run.sh make update-dev-resources` to regenerate CRDs, DeepCopy methods, and related manifests.
- After modifying `api/v2/checluster_types.go`, always run `make update-dev-resources`
(or `build/scripts/docker-run.sh make update-dev-resources` on macOS) to regenerate CRDs, DeepCopy methods, and related manifests.
- v2 is the storage version. v1 exists only for conversion compatibility and does not need to be updated.
- Webhook validation and defaulting logic live in `api/v2/checluster_webhook.go`.
- `zz_generated.deepcopy.go` files are generated by `controller-gen` — never edit them manually.
10 changes: 10 additions & 0 deletions .claude/rules/build-and-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Build & Test Commands

- Build: `make build`
- All unit tests: `make test`
- Single package: `MOCK_API=true go test -mod=vendor ./package/...`
- Single test: `MOCK_API=true go test -mod=vendor ./package/... -run TestSpecificName -v`
- Format: `make fmt`
- Vet: `make vet`
- Lint: `make lint`
- After making changes, always build and run the relevant tests before reporting the task as complete.
6 changes: 6 additions & 0 deletions .claude/rules/code-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Code Style Rules

- Add an empty line after logical blocks of code (e.g., after `if` blocks, loops, variable declaration groups) to improve readability.
- Wrap errors with context using `fmt.Errorf` at every call site instead of passing them through directly — this applies both inside the function and at the caller. When the object has a namespace, include it as `namespace/name` in the message. Use `return fmt.Errorf("failed to sync deployment %s/%s: %w", obj.Namespace, obj.Name, err)` instead of `return err`.
- Lines should not exceed 120 characters. If a function call exceeds this limit, put each argument on its own line. This does not apply to `fmt.Errorf`, `fmt.Sprintf`, and similar formatting functions — keep those on one line.
- Use `deploy.GetLabels(component)` for labeling resources in `pkg/deploy/` reconcilers.
8 changes: 8 additions & 0 deletions .claude/rules/k8s-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# K8s Client Rules

- Use the `K8sClient` wrapper (`pkg/common/k8s-client/`) for all Kubernetes operations.
- Access it via `DeployContext.ClusterAPI.ClientWrapper` (cached) or `DeployContext.ClusterAPI.NonCachingClientWrapper` (non-caching).
- **Do NOT use** the legacy functions from `pkg/deploy/sync.go` (`deploy.Sync`, `deploy.Get*`, `deploy.Delete*`, `deploy.CreateIgnoreIfExists`) — that file is deprecated.
- When using `Sync` to create/update an object in the **same namespace** as the CheCluster CR, set the owner reference before syncing: `controllerutil.SetControllerReference(ctx.CheCluster, obj, ctx.ClusterAPI.Scheme)`. Do **not** set owner references on objects in other namespaces (cross-namespace owner references are not supported by Kubernetes).
- When using `Sync`, always pass `&k8sclient.SyncOptions{DiffOpts: diffs.<Type>}` to control which fields are compared. Diff options live in `pkg/common/diffs/diffs.go`. If no diff option exists for the resource type, add one there first.
- When deleting, use `DeleteByKeyIgnoreNotFound` for idempotent cleanup (e.g., toggling a feature off).
5 changes: 5 additions & 0 deletions .claude/rules/kubebuilder-defaults.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Kubebuilder Default Propagation Rule

- When adding a `+kubebuilder:default` annotation to a field, propagate the default up to every parent struct's `+kubebuilder:default` annotation as well.
- If the parent struct already has a `+kubebuilder:default`, add the new nested default to it. If it doesn't, add one.
- This is required because kubebuilder only applies a field's default when its parent object is non-nil. A pointer field (`*Foo`) with a default on its inner fields has no effect if the parent's default doesn't instantiate it.
7 changes: 7 additions & 0 deletions .claude/rules/pull-requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Pull Request Rules

- When creating a PR, use the project's PR template from `.github/PULL_REQUEST_TEMPLATE.md`.
- Fill in all sections: "What does this PR do?", "Screenshot/screencast of this PR", "What issues does this PR fix or reference?", and "How to test this PR?".
- Include deployment and test steps appropriate for the change (OpenShift via `test-catalog-from-sources.sh`, Minikube via `test-operator-from-sources.sh`, or both).
- Check all applicable items in the "Common Test Scenarios" checklist (deploy, start workspace, terminal, stop workspace, check operator logs).
- Check all applicable items in the "PR Checklist" (ECA, code complete, builds, tests, devfile, docs, CI/CD).
10 changes: 2 additions & 8 deletions .claude/rules/reconcilers.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
---
paths:
- "pkg/deploy/**"
- "controllers/che/**"
---

# Reconciler Rules

- Every component reconciler implements the `Reconcilable` interface (`pkg/common/reconciler/reconcile_manager.go`): `Reconcile()` and `Finalize()`.
- `Reconcile()` returns `(result, done, err)` — return `done=true` only when the component is fully reconciled.
The pipeline stops at the first `done=false`. Use `RequeueAfter: time.Second` in `result` for error recovery and when dealing with cluster-scoped objects.
- `Reconcile()` returns `(result, done, err)` — return `done=true` only when the component is fully reconciled. The pipeline stops at the first `done=false`. Use `RequeueAfter: time.Second` in `result` for error recovery and when dealing with cluster-scoped objects.
- Registration order in `controllers/che/checluster_controller.go` matters — reconcilers run sequentially and may depend on earlier ones having completed.
- All reconcilers receive `DeployContext` (`pkg/common/chetypes/types.go`) — use its `ClusterAPI` clients for k8s operations, not standalone clients.
- Some reconcilers are OpenShift-only (consolelink, container-capabilities) — guard with `infrastructure.IsOpenShift()`.
- The usernamespace controller (`controllers/usernamespace/`) is a separate controller, not a `Reconcilable` — it has its own `Reconcile(ctx, req)` method and manages per-user namespace resources.
6 changes: 6 additions & 0 deletions .claude/rules/redhat-compliance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Red Hat Compliance Rules

- If a code suggestion matches known open-source code, include the original license text and copyright notice. Do not suggest code whose license compatibility with EPL-2.0 cannot be verified.
- When suggesting commit messages, include `Assisted-by: {AGENT_NAME}` trailer (e.g., `Assisted-by: Claude Opus 4.6`).
- Never include credentials, tokens, or secrets in code.
- All new Go files must include the EPL-2.0 copyright header (copy from any existing file in the repo). This does not apply to files in the `vendor/` directory.
4 changes: 4 additions & 0 deletions .claude/rules/resource-naming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Resource Naming Rules

- Resource names must not hardcode `eclipse-che`, `che`, or `devspaces`. Use `defaults.GetCheFlavor()` (from `pkg/common/operator-defaults`) to make names work for both upstream (`eclipse-che`/`che`) and downstream (`devspaces`).
- This applies to Kubernetes object names, label values, and any string embedded in resource specs that identifies the product. Constants like `constants.CheEclipseOrg` are fine — they are shared across both flavors.
6 changes: 6 additions & 0 deletions .claude/rules/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Testing Rules

- Use `test.NewCtxBuilder()` to create test `DeployContext` instances with a fake k8s client.
- Use `infrastructure.InitializeForTesting(infrastructure.OpenShiftV4)` or `infrastructure.Kubernetes` to set the platform. Use OpenShift when testing OpenShift-specific resources (e.g., network policies with `infrastructure.IsOpenShift()` guards).
- Use `defaults.InitializeForTesting("../../config/manager/manager.yaml")` in `init_test.go` (adjust relative path) to load operator defaults for `GetCheFlavor()` and other defaults.
- Tests are co-located with source files (`*_test.go`). Test helpers live in `pkg/common/test/`.
70 changes: 11 additions & 59 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,24 @@
# AGENTS.md

This file provides guidance to AI coding agents when working with code in this repository.
This file provides architectural context for AI coding agents working in this repository.
Actionable rules (build commands, code style, K8s client usage, compliance) live in `.claude/rules/`.

## Project Overview

Eclipse Che Operator — a Kubernetes/OpenShift operator built with Operator SDK and controller-runtime that manages
the lifecycle of Eclipse Che installations. It watches `CheCluster` custom resources and reconciles all Che components
Eclipse Che Operator — a Kubernetes/OpenShift operator built with Operator SDK and controller-runtime that manages
the lifecycle of Eclipse Che installations. It watches `CheCluster` custom resources and reconciles all Che components
(dashboard, gateway, devfile registry, Che server, etc.).

Go module: `github.com/eclipse-che/che-operator`

## Build & Test Commands

```bash
# Build operator binary
make build

# Run all unit tests
make test

# Run a single test file or package
MOCK_API=true go test -mod=vendor ./controllers/che/... -run TestSpecificName -v

# Run tests for a specific package
MOCK_API=true go test -mod=vendor ./pkg/deploy/gateway/...

# Format code (uses goimports if available, falls back to go fmt)
make fmt

# Run go vet
make vet

# Run static code analyzers
make lint

# Regenerate CRDs, DeepCopy methods, and related manifests
build/scripts/docker-run.sh make update-dev-resources

# Build operator Docker image
make docker-build IMG=<image>
```

## Architecture

### CRD & API Versions

- **v2** (`api/v2/`) — current storage version. `CheClusterSpec` has top-level sections: `DevEnvironments`, `Components`, `GitServices`, `Networking`, `ContainerRegistry`.
- **v1** (`api/v1/`) — deprecated
- **v1** (`api/v1/`) — deprecated, exists only for conversion compatibility.
- Webhooks (validation, defaulting, conversion) live in `api/v2/checluster_webhook.go`.

After modifying `api/v2/checluster_types.go`, run `build/scripts/docker-run.sh make update-dev-resources`.

### Controller Structure

**Entry point:** `cmd/main.go` — registers four controllers with the manager:
Expand All @@ -62,24 +30,18 @@ After modifying `api/v2/checluster_types.go`, run `build/scripts/docker-run.sh m

### Reconciliation Pipeline

`CheClusterReconciler` uses a `ReconcilerManager` (`pkg/common/reconciler/`) that runs a chain of
`Reconcilable` implementations **in order**. Each reconciler returns `(result, done, err)` — the chain stops
at the first `done=false`. Registration order in `controllers/che/checluster_controller.go` defines the execution order:
`CheClusterReconciler` uses a `ReconcilerManager` (`pkg/common/reconciler/`) that runs a chain of
`Reconcilable` implementations **in order**. Each reconciler returns `(result, done, err)` — the chain stops
at the first `done=false`. Registration order in `controllers/che/checluster_controller.go` defines the execution order.

### DeployContext

`DeployContext` (`pkg/common/chetypes/types.go`) is the central context object passed to every reconciler. It carries:
- `CheCluster` — the CR being reconciled
- `ClusterAPI` — cached and non-cached k8s clients, discovery client
- `ClusterAPI` — cached and non-cached k8s clients, discovery client, `ClientWrapper` / `NonCachingClientWrapper`
- `Proxy`, `Authentication` — resolved configuration
- `IsSelfSignedCertificate`, `CheHost`, `DwoNamespace`

### Kubernetes Client Usage

Use the `K8sClient` wrapper (`pkg/common/k8s-client/`) for all Kubernetes operations. Access it via `DeployContext.ClusterAPI.ClientWrapper` (cached) or `DeployContext.ClusterAPI.NonCachingClientWrapper` (non-caching, for cluster-scoped or cross-namespace objects). Key methods: `Sync`, `Create`, `CreateIfNotExists`, `GetIgnoreNotFound`, `DeleteByKeyIgnoreNotFound`, `List`.

**Do NOT use** the legacy functions from `pkg/deploy/sync.go` (`deploy.Sync`, `deploy.Get*`, `deploy.Delete*`, `deploy.CreateIgnoreIfExists`, etc.) — that file is deprecated.

### Component Packages (`pkg/deploy/`)

Each Che component has its own package under `pkg/deploy/` (e.g., `dashboard/`, `gateway/`, `postgres/`, `identity-provider/`, `server/`). Each package typically contains:
Expand All @@ -89,12 +51,12 @@ Each Che component has its own package under `pkg/deploy/` (e.g., `dashboard/`,

### Platform Detection

`pkg/common/infrastructure/` detects Kubernetes vs OpenShift and feature availability (OAuth, image puller, service monitors).
`pkg/common/infrastructure/` detects Kubernetes vs OpenShift and feature availability (OAuth, image puller, service monitors).
Some reconcilers are conditionally registered based on platform (e.g., `ConsoleLink` and `ContainerCapabilities` are OpenShift-only).

### Operator Defaults

`pkg/common/operator-defaults/` reads default container images and configuration from environment variables.
`pkg/common/operator-defaults/` reads default container images and configuration from environment variables.
Resource limit/request defaults live in `pkg/common/constants/`.

### Testing
Expand All @@ -119,13 +81,3 @@ build/scripts/olm/test-catalog-from-sources.sh
# Minikube
build/scripts/minikube-tests/test-operator-from-sources.sh
```

## Code Style

- Add an empty line after logical blocks of code (e.g., after `if` blocks, loops, variable declaration groups) to improve readability.
- Wrap errors with context using `fmt.Errorf` instead of passing them through directly. For example, use `return fmt.Errorf("failed to sync deployment: %w", err)` instead of `return err`.
- After modifying `api/v2/checluster_types.go`, run `make update-dev-resources` to regenerate CRDs, DeepCopy methods, and related manifests. On macOS, use `build/scripts/docker-run.sh make update-dev-resources` instead.

## Red Hat Compliance and Responsible AI Rules

See [redhat-compliance-and-responsible-ai.md](redhat-compliance-and-responsible-ai.md) and the Cursor rules file under `.cursor/rules/`.
35 changes: 35 additions & 0 deletions api/v2/checluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,28 @@ type CheClusterSpecNetworking struct {
// +optional
// +kubebuilder:default:={gateway: {configLabels: {app: che, component: che-gateway-config}}}
Auth Auth `json:"auth"`
// NetworkPolicy configures NetworkPolicy resources for the Che namespace
// and user workspace namespaces. For OpenShift clusters only.
// When enabled, the following policies are created:
// In the Che namespace:
// - allow-from-same-namespace: allows ingress traffic between Che pods in the same namespace.
// - allow-from-workspaces-namespaces-to-openvsx-registry: allows ingress traffic from user workspace
Comment thread
tolusha marked this conversation as resolved.
// namespaces to the OpenVSX registry.
// - allow-from-workspaces-namespaces-to-plugin-registry: allows ingress traffic from user workspace
// namespaces to the plugin registry.
// - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace.
// - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace.
// - allow-from-operator: allows ingress traffic from the operator pod to Che components.
// - allow-all-egress: allows all egress traffic from Che pods.
// In each user workspace namespace:
// - allow-from-<che-namespace>: allows ingress traffic from the Che namespace.
// - allow-from-same-namespace: allows ingress traffic between pods in the same namespace.
// - allow-from-devworkspace-operator: allows ingress traffic from the DevWorkspace operator.
// - allow-from-openshift-monitoring: allows ingress traffic from the OpenShift monitoring namespace.
// - allow-from-openshift-ingress: allows ingress traffic from the OpenShift ingress namespace.
// - allow-all-egress: allows all egress traffic from workspace pods.
// +optional
NetworkPolicy *NetworkPolicy `json:"networkPolicy,omitempty"`
}

type DevEnvironmentNetworking struct {
Expand All @@ -337,6 +359,14 @@ type DevEnvironmentNetworking struct {
ExternalTLSConfig *ExternalTLSConfig `json:"externalTLSConfig,omitempty"`
}

// NetworkPolicy configuration settings.
// +k8s:openapi-gen=true
type NetworkPolicy struct {
// Enabled controls whether the operator creates NetworkPolicy resources.
// +optional
Enabled *bool `json:"enabled"`
Comment thread
tolusha marked this conversation as resolved.
}

type ExternalTLSConfig struct {
// Enabled determines whether external TLS configuration is used.
// If set to true, the operator will not set TLS config for ingress/route objects.
Expand Down Expand Up @@ -1259,3 +1289,8 @@ func (c *CheCluster) IsDevEnvironmentExternalTLSConfigEnabled() bool {
c.Spec.DevEnvironments.Networking.ExternalTLSConfig != nil &&
*c.Spec.DevEnvironments.Networking.ExternalTLSConfig.Enabled
}

func (c *CheCluster) IsNetworkPoliciesEnabled() bool {
return c.Spec.Networking.NetworkPolicy != nil &&
ptr.Deref(c.Spec.Networking.NetworkPolicy.Enabled, constants.NetworkPolicyEnabled)
}
25 changes: 25 additions & 0 deletions api/v2/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ metadata:
categories: Developer Tools
certified: "false"
containerImage: quay.io/eclipse/che-operator:next
createdAt: "2026-07-24T14:28:09Z"
createdAt: "2026-07-28T11:33:09Z"
description: A Kube-native development solution that delivers portable and collaborative
developer workspaces.
features.operators.openshift.io/cnf: "false"
Expand All @@ -108,7 +108,7 @@ metadata:
operatorframework.io/arch.amd64: supported
operatorframework.io/arch.arm64: supported
operatorframework.io/os.linux: supported
name: eclipse-che.v7.121.0-1044.next
name: eclipse-che.v7.121.0-1050.next
namespace: placeholder
spec:
apiservicedefinitions: {}
Expand Down Expand Up @@ -1173,7 +1173,7 @@ spec:
name: openvsx
- image: quay.io/sclorg/postgresql-16-c9s:20260319
name: openvsx-postgres
version: 7.121.0-1044.next
version: 7.121.0-1050.next
webhookdefinitions:
- admissionReviewVersions:
- v1
Expand Down
Loading
Loading