Skip to content

Commit 5a4bea4

Browse files
committed
feat: enforce pod switch, theme, update status crd
Signed-off-by: will <[email protected]>
1 parent 251813d commit 5a4bea4

File tree

16 files changed

+203
-44
lines changed

16 files changed

+203
-44
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
<p align="left">
5-
<img width="200" height="200" src="./public/imageshift.png">
5+
<img width="200" height="200" src="./imageshift-icon.svg" alt="ImageShift Logo">
66
</p>
77

88

@@ -53,8 +53,8 @@ helm install \
5353
### Prerequisites
5454
- go version v1.23.0+
5555
- docker version 17.03+.
56-
- kubectl version v1.11.3+.
57-
- Access to a Kubernetes v1.11.3+ cluster.
56+
- kubectl version v1.19+.
57+
- Access to a Kubernetes v1.19+ cluster (mutating webhooks required).
5858

5959
### To Deploy on the cluster
6060
**Build and push your image to the location specified by `IMG`:**
@@ -155,7 +155,15 @@ previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml
155155
is manually re-applied afterwards.
156156

157157
## Contributing
158-
// TODO(user): Add detailed information on how you would like others to contribute to this project
158+
159+
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
160+
161+
### Quick Start for Contributors
162+
163+
1. Fork and clone the repository
164+
2. Run `make test` to verify the test suite passes
165+
3. Create a feature branch and make your changes
166+
4. Submit a pull request
159167

160168
**NOTE:** Run `make help` for more information on all potential `make` targets
161169

api/v1/imageshift_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ type ImageshiftSpec struct {
4040

4141
// +default:value="imageshift.dev"
4242
NamespaceSelector string `json:"namespaceSelector"`
43+
44+
// EnforceExistingPods when true, the controller will delete pods that have
45+
// images not matching the swap rules. This forces pod recreation with correct images.
46+
// Default: false (disabled)
47+
// +optional
48+
EnforceExistingPods bool `json:"enforceExistingPods,omitempty"`
4349
}
4450

4551
type ImageshiftMapping struct {

api/v1/zz_generated.deepcopy.go

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/imageshift.dev_imageshifts.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ spec:
4242
default:
4343
default: docker.io
4444
type: string
45+
enforceExistingPods:
46+
description: |-
47+
EnforceExistingPods when true, the controller will delete pods that have
48+
images not matching the swap rules. This forces pod recreation with correct images.
49+
Default: false (disabled)
50+
type: boolean
4551
mappings:
4652
properties:
4753
exactSwap:

docs/docs/installation/prerequisites.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ Before installing ImageShift, ensure your environment meets the following requir
88

99
## Kubernetes Version
1010

11-
- **Kubernetes 1.35+** is required
11+
- **Kubernetes 1.19+** is required
1212
- The mutating admission webhook API must be enabled (enabled by default)
1313

1414
Verify your Kubernetes version:
1515

1616
```bash
17-
kubectl version --short
17+
kubectl version
1818
```
1919

2020
## kubectl

docs/docs/reference/configuration.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ kubectl label namespace prod-api imageshift.dev=enabled
239239
kubectl label namespace dev-app imageshift.dev-
240240
```
241241

242+
## Registry Normalization
243+
244+
ImageShift normalizes registry names to handle aliases. For example:
245+
246+
- `docker.io` is equivalent to `index.docker.io` (Docker Hub's canonical name)
247+
- Images without a registry prefix (e.g., `nginx:latest`) use the `spec.default` registry
248+
249+
This means you can use `docker.io` in your swap rules and it will match images specified as either `docker.io/nginx` or `nginx` (when default is `docker.io`).
250+
242251
## Tips for Writing Regex Patterns
243252

244253
### Escape Special Characters

docs/docs/reference/crd.md

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ The Imageshift resource defines image mapping rules that are applied to pods cre
2222

2323
| Field | Type | Default | Description |
2424
|-------|------|---------|-------------|
25-
| `spec.default` | string | `"docker.io"` | The default registry for images without an explicit registry |
26-
| `spec.namespaceSelector` | string | `"imageshift.dev"` | The label key used to identify namespaces for image swapping |
25+
| `spec.default` | string | `"docker.io"` | The default registry assumed for images without an explicit registry prefix (e.g., `nginx` becomes `docker.io/library/nginx`) |
26+
| `spec.namespaceSelector` | string | `"imageshift.dev"` | Reserved for future use. Currently ignored - namespaces must use label `imageshift.dev=enabled` |
27+
| `spec.enforceExistingPods` | boolean | `false` | When enabled, the controller will delete pods that have images not matching the swap rules, forcing pod recreation with correct images |
2728
| `spec.mappings` | object | | Container for all mapping rules |
2829

2930
### Mappings
@@ -154,11 +155,38 @@ spec:
154155
target: "registry.internal.example.com/ecr/$1/$2/$3"
155156
```
156157

157-
## Namespace Selection
158+
## Enforcing Existing Pods
159+
160+
By default, ImageShift only mutates pods at creation time via the admission webhook. Pods that already exist when ImageShift is installed or when rules are changed will not be affected.
161+
162+
To enforce image swap rules on existing pods, enable the `enforceExistingPods` field:
163+
164+
```yaml
165+
apiVersion: imageshift.dev/v1
166+
kind: Imageshift
167+
metadata:
168+
name: imageshift
169+
spec:
170+
enforceExistingPods: true
171+
mappings:
172+
swap:
173+
- registry: docker.io
174+
target: registry.internal.example.com/dockerhub
175+
```
158176

159-
ImageShift only processes pods in namespaces that have the selector label set to `enabled`.
177+
:::warning
178+
**This is a disruptive operation.** When enabled, the controller will **delete** any pods in labeled namespaces that have images not matching the current swap rules. This forces the pods to be recreated by their controllers (Deployment, StatefulSet, etc.) with the correct images applied by the webhook.
160179

161-
Default selector label: `imageshift.dev=enabled`
180+
Only enable this feature when you understand the impact:
181+
- Pods will be deleted and recreated
182+
- Stateless workloads managed by controllers will recover automatically
183+
- Standalone pods (not managed by a controller) will be permanently deleted
184+
- Brief service interruptions may occur during pod recreation
185+
:::
186+
187+
## Namespace Selection
188+
189+
ImageShift only processes pods in namespaces that have the label `imageshift.dev=enabled`.
162190

163191
To enable a namespace:
164192

@@ -172,29 +200,59 @@ To disable a namespace:
172200
kubectl label namespace my-namespace imageshift.dev-
173201
```
174202

175-
To use a custom selector label, set `spec.namespaceSelector`:
203+
:::note
204+
The `spec.namespaceSelector` field is reserved for future use. Currently, ImageShift always uses `imageshift.dev` as the label key.
205+
:::
206+
207+
## Pod Annotations and Labels
208+
209+
When ImageShift mutates a pod, it adds the following metadata:
210+
211+
### Labels
212+
213+
| Label | Value | Description |
214+
|-------|-------|-------------|
215+
| `imageshift.dev/mutated` | `true` | Added when at least one container image was swapped |
216+
217+
### Annotations
218+
219+
For each mutated container, ImageShift stores the original image reference:
220+
221+
| Annotation Pattern | Description |
222+
|--------------------|-------------|
223+
| `<container-name>.container.imageshift.dev/original` | Original image for regular containers |
224+
| `<container-name>.initContainer.imageshift.dev/original` | Original image for init containers |
225+
226+
Example for a pod with an nginx container:
176227

177228
```yaml
178-
spec:
179-
namespaceSelector: custom-label.example.com
229+
metadata:
230+
labels:
231+
imageshift.dev/mutated: "true"
232+
annotations:
233+
nginx.container.imageshift.dev/original: "nginx:latest"
180234
```
181235

182-
Then label namespaces with:
236+
You can use these annotations to verify mutations or for debugging:
183237

184238
```bash
185-
kubectl label namespace my-namespace custom-label.example.com=enabled
239+
kubectl get pod <pod-name> -o jsonpath='{.metadata.annotations}' | jq .
186240
```
187241

188242
## Limitations
189243

190244
- Only one Imageshift resource can exist in the cluster at a time
191245
- The validating webhook rejects creation of additional Imageshift resources
192-
- Init containers and ephemeral containers are also processed
246+
- Init containers are also processed
193247
- Images in Pod templates (Deployments, StatefulSets, etc.) are processed when Pods are created
194248

195249
## Status
196250

197-
The Imageshift resource does not currently expose status fields. Future versions may include:
198-
- Count of processed pods
199-
- Last reconciliation time
200-
- Error conditions
251+
The Imageshift resource exposes the following status fields:
252+
253+
| Field | Type | Description |
254+
|-------|------|-------------|
255+
| `conditions` | array | Standard Kubernetes conditions for the resource |
256+
| `lastReconciled` | timestamp | When the resource was last successfully reconciled |
257+
| `configValid` | boolean | Whether the current configuration is valid |
258+
| `mutatedPodCount` | integer | Total number of pods that have been mutated |

docs/docusaurus.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ const config = {
4545
title: 'ImageShift',
4646
logo: {
4747
alt: 'ImageShift Logo',
48-
src: 'img/logo.svg',
48+
src: 'img/imageshift-icon-light.svg',
49+
srcDark: 'img/imageshift-icon-dark.svg',
4950
},
5051
items: [
5152
{

docs/src/components/SchemaExplorer/schemaData.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ export const schemaData = {
5656
default: 'imageshift.dev',
5757
description: 'The label key used to identify namespaces for image swapping',
5858
},
59+
{
60+
name: 'enforceExistingPods',
61+
type: 'boolean',
62+
required: false,
63+
default: false,
64+
description: 'When true, the controller will delete pods that have images not matching the swap rules, forcing pod recreation with correct images',
65+
},
5966
{
6067
name: 'mappings',
6168
type: 'object',
@@ -139,8 +146,33 @@ export const schemaData = {
139146
name: 'status',
140147
type: 'object',
141148
required: false,
142-
description: 'ImageshiftStatus defines the observed state of Imageshift (currently unused)',
143-
children: [],
149+
description: 'ImageshiftStatus defines the observed state of Imageshift',
150+
children: [
151+
{
152+
name: 'conditions',
153+
type: 'array',
154+
required: false,
155+
description: 'Standard Kubernetes conditions for the resource',
156+
},
157+
{
158+
name: 'lastReconciled',
159+
type: 'string',
160+
required: false,
161+
description: 'Timestamp of the last successful reconciliation',
162+
},
163+
{
164+
name: 'configValid',
165+
type: 'boolean',
166+
required: false,
167+
description: 'Whether the current configuration is valid',
168+
},
169+
{
170+
name: 'mutatedPodCount',
171+
type: 'integer',
172+
required: false,
173+
description: 'Total number of pods that have been mutated',
174+
},
175+
],
144176
},
145177
],
146178
};
Lines changed: 9 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)