Repository: cdk8s-team/cdk8s-plus (ts)

Issue:
Sidecar containers cannot specify probes
### Description of the feature or enhancement:
Sidecar containers, unlike init containers, [support probes](https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#differences-from-init-containers). `addInitContainer` doesn't support this and will throw an error if `liveness`, `readiness`, or `startup` are specified:
https://github.com/cdk8s-team/cdk8s-plus/blob/f7c11148f65084b35fb5d3273a31af387015bc8f/src/pod.ts#L124-L135

I'd like to be able to specify these probes for sidecar containers. 

### Use Case:
Since a sidecar container does not exit before the main container starts, probes are the only means available for delaying the startup of the main container beyond the simplest possible cases. Sidecar containers may require some time to be ready after starting, and in my case it's important that the sidecar container be _ready_, not just _started_, by the time the main container starts.

### Proposed Solution:

It seems relatively straightforward to build on #3812 and disable the exceptions if `restartPolicy` is specified.

### Other:

* [x] :wave: I may be able to implement this feature request
* [ ] :warning: This feature might incur a breaking change

---

This is a :rocket: Feature Request

Pull request description:
fix(pod): allow sidecar containers to have probes
https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#differences-from-regular-containers

if we check docs, sidecar containers support readiness, liveness and startup probes. I added an extra check to make sure the init container is not sidecar for probe checks.

this way it will be possible to add probes for initcontainers when they are sidecar.

edit: this should be backported to k8s-29/main as well

Fixes #4338 

Patch:
diff --git a/src/pod.ts b/src/pod.ts
index c7f4ea6b..3ac602bc 100644
--- a/src/pod.ts
+++ b/src/pod.ts
@@ -122,15 +122,15 @@ export abstract class AbstractPod extends base.Resource implements IPodSelector,
   public addInitContainer(cont: container.ContainerProps): container.Container {
 
     // https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#differences-from-regular-containers
-    if (cont.readiness) {
+    if (!this.isSidecarContainer(cont) && cont.readiness) {
       throw new Error('Init containers must not have a readiness probe');
     }
 
-    if (cont.liveness) {
+    if (!this.isSidecarContainer(cont) && cont.liveness) {
       throw new Error('Init containers must not have a liveness probe');
     }
 
-    if (cont.startup) {
+    if (!this.isSidecarContainer(cont) && cont.startup) {
       throw new Error('Init containers must not have a startup probe');
     }
 
@@ -143,6 +143,13 @@ export abstract class AbstractPod extends base.Resource implements IPodSelector,
     return impl;
   }
 
+  // Any initContainer that has `restartPolicy=Always` is a sidecar container. Please refer to
+  // documentation for more details:
+  // https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#differences-from-init-containers
+  private isSidecarContainer(cont: container.ContainerProps) {
+    return cont.restartPolicy === container.ContainerRestartPolicy.ALWAYS;
+  }
+
   public addHostAlias(hostAlias: HostAlias): void {
     this._hostAliases.push(hostAlias);
   }


Test patch:
diff --git a/test/pod.test.ts b/test/pod.test.ts
index 977e64da..17f44567 100644
--- a/test/pod.test.ts
+++ b/test/pod.test.ts
@@ -254,6 +254,45 @@ test('init containers cannot have startup probe', () => {
 
 });
 
+test('sidecar containers can have liveness probe', () => {
+
+  const chart = Testing.chart();
+  const pod = new kplus.Pod(chart, 'Pod', { containers: [{ image: 'image' }] });
+
+  pod.addInitContainer({ image: 'image', liveness: Probe.fromTcpSocket(), restartPolicy: ContainerRestartPolicy.ALWAYS });
+
+  const spec = Testing.synth(chart)[0].spec;
+
+  expect(spec.initContainers[0].livenessProbe).toBeTruthy();
+
+});
+
+test('sidecar containers can have readiness probe', () => {
+
+  const chart = Testing.chart();
+  const pod = new kplus.Pod(chart, 'Pod', { containers: [{ image: 'image' }] });
+
+  pod.addInitContainer({ image: 'image', readiness: Probe.fromTcpSocket(), restartPolicy: ContainerRestartPolicy.ALWAYS });
+
+  const spec = Testing.synth(chart)[0].spec;
+
+  expect(spec.initContainers[0].readinessProbe).toBeTruthy();
+
+});
+
+test('sidecar containers can have startup probe', () => {
+
+  const chart = Testing.chart();
+  const pod = new kplus.Pod(chart, 'Pod', { containers: [{ image: 'image' }] });
+
+  pod.addInitContainer({ image: 'image', startup: Probe.fromTcpSocket(), restartPolicy: ContainerRestartPolicy.ALWAYS });
+
+  const spec = Testing.synth(chart)[0].spec;
+
+  expect(spec.initContainers[0].startupProbe).toBeTruthy();
+
+});
+
 test('can specify init containers at instantiation', () => {
 
   const chart = Testing.chart();