Skip to content

Commit 709f4da

Browse files
dhaiducekopenshift-merge-bot[bot]
authored andcommitted
Add CLAUDE.md
Assisted-by: Claude code Signed-off-by: Dale Haiducek <19750917+dhaiducek@users.noreply.github.com>
1 parent 265c8e7 commit 709f4da

File tree

1 file changed

+152
-0
lines changed

1 file changed

+152
-0
lines changed

CLAUDE.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
The Policy Generator is a Kustomize exec plugin that constructs Open Cluster Management policies from Kubernetes YAML files. It's a Go binary that processes PolicyGenerator Custom Resources and outputs Policy, Placement, and PlacementBinding manifests.
8+
9+
## Build Commands
10+
11+
```bash
12+
# Build the plugin (installs to ~/.config/kustomize/plugin/...)
13+
make build
14+
15+
# Build binary in repository root (for standalone use)
16+
make build-binary
17+
18+
# Run all tests
19+
make test
20+
21+
# Run tests with coverage
22+
make test-coverage
23+
24+
# Run single test
25+
go test -v -run TestName ./internal
26+
27+
# Build release binaries for all platforms
28+
make build-release
29+
```
30+
31+
## Testing
32+
33+
Tests use the standard Go testing framework. Test files are colocated with source files (e.g., `plugin.go` has `plugin_test.go`).
34+
35+
## Development Workflow
36+
37+
Before submitting PRs:
38+
```bash
39+
make fmt
40+
make lint
41+
make test
42+
```
43+
44+
## High-Level Architecture
45+
46+
### Core Flow
47+
48+
1. **Input**: PolicyGenerator YAML manifest (custom resource)
49+
2. **Processing**: Plugin.Config() validates and applies defaults → Plugin.Generate() creates policies
50+
3. **Output**: YAML stream with Policy, Placement, and PlacementBinding manifests
51+
52+
### Key Components
53+
54+
**cmd/PolicyGenerator/main.go**
55+
- Entry point that reads PolicyGenerator YAML files
56+
- Calls Plugin.Config() then Plugin.Generate()
57+
- Outputs YAML to stdout (for Kustomize consumption)
58+
59+
**internal/plugin.go** (Plugin struct)
60+
- `Config()`: Validates input, applies defaults, sets base directory
61+
- `Generate()`: Main generation orchestrator
62+
- Creates policies via `createPolicy()`
63+
- Creates policy sets via `createPolicySet()`
64+
- Creates placements (consolidated where possible)
65+
- Creates placement bindings
66+
- Placement consolidation: Tracks cluster/label selectors in `csToPlc` map to reuse placements when selectors match
67+
68+
**internal/types/types.go**
69+
- Defines all configuration structs:
70+
- `PolicyConfig`: Individual policy specification
71+
- `PolicyDefaults`: Default values applied to all policies
72+
- `PolicySetConfig`: Policy set groupings
73+
- `PlacementConfig`: Cluster targeting configuration
74+
- `Manifest`: References to Kubernetes manifests to wrap in policies
75+
76+
**internal/expanders/**
77+
- Policy expanders create additional policies for specific policy engines (Gatekeeper, Kyverno)
78+
- Each expander implements the interface in `expanders.go`
79+
- Enabled by default via `InformGatekeeperPolicies` and `InformKyvernoPolicies` flags
80+
81+
**internal/patches.go**
82+
- Handles Kustomize-style patching of manifests using strategic merge or JSON patches
83+
- OpenAPI schema support for patching non-Kubernetes CRs with list fields
84+
85+
**internal/utils.go**
86+
- Helper functions for manifest processing, YAML/JSON conversion, file operations
87+
88+
### Default Handling
89+
90+
The plugin has a sophisticated defaults system:
91+
- Hard-coded defaults in `defaults` variable (internal/plugin.go:77)
92+
- User-specified `policyDefaults` in PolicyGenerator YAML
93+
- Per-policy overrides in `policies` array
94+
- Per-manifest overrides in `manifests` array
95+
96+
The `applyDefaults()` method (internal/plugin.go:446) cascades these defaults in order, considering:
97+
- Explicit false values (requires checking raw YAML via `unmarshaledConfig`)
98+
- Special relationships (e.g., `orderManifests=true` forces `consolidateManifests=false`)
99+
100+
### Placement Logic
101+
102+
**Consolidation**: Multiple policies can share a Placement if they have identical cluster/label selectors. The `csToPlc` map tracks selector → placement name mappings.
103+
104+
**Kind Selection**: Plugin supports both Placement (cluster.open-cluster-management.io/v1beta1) and deprecated PlacementRule (apps.open-cluster-management.io/v1). Cannot mix in single PolicyGenerator.
105+
106+
**Placement Sources**:
107+
1. External file via `placementPath` or `placementRulePath`
108+
2. Referenced by name via `placementName` or `placementRuleName`
109+
3. Generated from inline `labelSelector` or `clusterSelector`
110+
111+
### Manifest Processing
112+
113+
Manifests can be:
114+
- Individual YAML/JSON files
115+
- Directories (processed recursively)
116+
- Kustomize directories (if not disabled via env var)
117+
118+
The generator wraps each manifest in a ConfigurationPolicy, which is then wrapped in a Policy template. Policy expanders may create additional inform-only policies for Gatekeeper/Kyverno resources.
119+
120+
## Environment Variables
121+
122+
- `POLICY_GEN_ENABLE_HELM`: Set to "true" to enable Helm processing in Kustomize directories
123+
- `POLICY_GEN_DISABLE_LOAD_RESTRICTORS`: Set to "true" to allow Helm directories outside Kustomize path
124+
125+
## Important Validation Rules
126+
127+
- Policy names must be DNS-compliant (RFC 1123)
128+
- Policy namespace + name must be ≤ 63 characters
129+
- Cannot mix Placement and PlacementRule kinds
130+
- `consolidateManifests` and `orderManifests` are mutually exclusive
131+
- `orderManifests` incompatible with `extraDependencies`
132+
- When consolidating manifests, all ConfigurationPolicy options must match at policy level
133+
134+
## Code Modification Guidance
135+
136+
**Adding a Policy Expander**:
137+
1. Create file in `internal/expanders/`
138+
2. Implement the expander interface
139+
3. Register in `getExpanders()` (expanders/expanders.go)
140+
4. Add boolean flag to `PolicyDefaults` and `PolicyConfig` structs (types/types.go)
141+
5. Add default handling in `applyDefaults()` (plugin.go)
142+
6. Update docs/policygenerator-reference.yaml
143+
144+
**Modifying Defaults**:
145+
- Edit `defaults` variable in internal/plugin.go
146+
- Update `applyDefaults()` method for cascade logic
147+
- Check both `PolicyDefaults` and `PolicyConfig` structs
148+
149+
**Adding Manifest Processing**:
150+
- Most logic is in `getPolicyTemplates()` (internal/utils.go)
151+
- Patching handled in internal/patches.go
152+
- Use `unmarshalManifestFile()` for reading YAML/JSON files

0 commit comments

Comments
 (0)