Skip to content

Commit 4fe7876

Browse files
committed
Add multi-architecture IPA support and configurable httpd probes
Signed-off-by: s3rj1k <[email protected]>
1 parent 3a67b89 commit 4fe7876

File tree

9 files changed

+762
-14
lines changed

9 files changed

+762
-14
lines changed

api/v1alpha1/ironic_types.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,28 @@ type Networking struct {
171171

172172
// DeployRamdisk defines IPA ramdisk settings.
173173
type DeployRamdisk struct {
174+
// DeployKernel sets DEPLOY_KERNEL URL for the IPA kernel.
175+
// Example: "file:///shared/html/images/ironic-python-agent.kernel"
176+
// +optional
177+
DeployKernel string `json:"deployKernel,omitempty"`
178+
179+
// DeployKernelByArch sets DEPLOY_KERNEL_BY_ARCH for multi-architecture support.
180+
// Format: arch1:url1,arch2:url2
181+
// Example: "x86_64:file:///shared/html/images/ipa.x86_64.kernel,aarch64:file:///shared/html/images/ipa.arm64.kernel"
182+
// +optional
183+
DeployKernelByArch string `json:"deployKernelByArch,omitempty"`
184+
185+
// DeployRamdisk sets DEPLOY_RAMDISK URL for the IPA ramdisk.
186+
// Example: "file:///shared/html/images/ironic-python-agent.initramfs"
187+
// +optional
188+
DeployRamdisk string `json:"deployRamdisk,omitempty"`
189+
190+
// DeployRamdiskByArch sets DEPLOY_RAMDISK_BY_ARCH for multi-architecture support.
191+
// Format: arch1:url1,arch2:url2
192+
// Example: "x86_64:file:///shared/html/images/ipa.x86_64.initramfs,aarch64:file:///shared/html/images/ipa.arm64.initramfs"
193+
// +optional
194+
DeployRamdiskByArch string `json:"deployRamdiskByArch,omitempty"`
195+
174196
// DisableDownloader tells the operator not to start the IPA downloader as the init container.
175197
// The user will be responsible for providing the right image to BareMetal Operator.
176198
// +optional
@@ -181,6 +203,16 @@ type DeployRamdisk struct {
181203
// +optional
182204
ExtraKernelParams string `json:"extraKernelParams,omitempty"`
183205

206+
// LivenessProbe configures the httpd container liveness probe.
207+
// If not set, defaults to checking /images/ironic-python-agent.kernel exists.
208+
// +optional
209+
LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"`
210+
211+
// ReadinessProbe configures the httpd container readiness probe.
212+
// If not set, defaults to checking /images/ironic-python-agent.kernel exists.
213+
// +optional
214+
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`
215+
184216
// SSHKey is the contents of the public key to inject into the ramdisk for debugging purposes.
185217
// +optional
186218
SSHKey string `json:"sshKey,omitempty"`

api/v1alpha1/zz_generated.deepcopy.go

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

config/crd/bases/ironic.metal3.io_ironics.yaml

Lines changed: 328 additions & 0 deletions
Large diffs are not rendered by default.

config/webhook/manifests.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
---
22
apiVersion: admissionregistration.k8s.io/v1
3+
kind: MutatingWebhookConfiguration
4+
metadata:
5+
name: mutating-webhook-configuration
6+
webhooks:
7+
- admissionReviewVersions:
8+
- v1
9+
clientConfig:
10+
service:
11+
name: webhook-service
12+
namespace: system
13+
path: /mutate-ironic-metal3-io-v1alpha1-ironic
14+
failurePolicy: Fail
15+
name: mutate-ironic.ironic.metal3.io
16+
rules:
17+
- apiGroups:
18+
- ironic.metal3.io
19+
apiVersions:
20+
- v1alpha1
21+
operations:
22+
- CREATE
23+
- UPDATE
24+
resources:
25+
- ironics
26+
sideEffects: None
27+
---
28+
apiVersion: admissionregistration.k8s.io/v1
329
kind: ValidatingWebhookConfiguration
430
metadata:
531
name: validating-webhook-configuration

internal/webhook/v1alpha1/ironic_webhook.go

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,55 +19,100 @@ package v1alpha1
1919
import (
2020
"context"
2121
"fmt"
22+
"net/url"
2223

2324
"k8s.io/apimachinery/pkg/runtime"
2425
ctrl "sigs.k8s.io/controller-runtime"
2526
logf "sigs.k8s.io/controller-runtime/pkg/log"
2627
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
2728

2829
metal3api "github.com/metal3-io/ironic-standalone-operator/api/v1alpha1"
29-
validation "github.com/metal3-io/ironic-standalone-operator/pkg/ironic"
30+
"github.com/metal3-io/ironic-standalone-operator/pkg/ironic"
3031
)
3132

33+
var deployBaseURL = url.URL{
34+
Scheme: "file",
35+
Path: "/shared/html",
36+
}
37+
3238
// log is for logging in this package.
3339
var ironiclog = logf.Log.WithName("webhooks").WithName("Ironic")
3440

3541
func SetupIronicWebhookWithManager(mgr ctrl.Manager) error {
3642
return ctrl.NewWebhookManagedBy(mgr).
3743
For(&metal3api.Ironic{}).
44+
WithDefaulter(&IronicCustomDefaulter{}).
3845
WithValidator(&IronicCustomValidator{}).
3946
Complete()
4047
}
4148

49+
// +kubebuilder:webhook:path=/mutate-ironic-metal3-io-v1alpha1-ironic,mutating=true,failurePolicy=fail,sideEffects=None,groups=ironic.metal3.io,resources=ironics,verbs=create;update,versions=v1alpha1,name=mutate-ironic.ironic.metal3.io,admissionReviewVersions=v1
50+
51+
type IronicCustomDefaulter struct{}
52+
53+
// Default implements webhook.Defaulter.
54+
func (r *IronicCustomDefaulter) Default(_ context.Context, obj runtime.Object) error {
55+
ir, ok := obj.(*metal3api.Ironic)
56+
if !ok {
57+
return fmt.Errorf("expected an Ironic, got %T", obj)
58+
}
59+
60+
ironiclog.Info("default", "name", ir.Name)
61+
62+
// Set default DeployKernel if neither DeployKernel nor DeployKernelByArch is set
63+
if ir.Spec.DeployRamdisk.DeployKernel == "" && ir.Spec.DeployRamdisk.DeployKernelByArch == "" {
64+
ir.Spec.DeployRamdisk.DeployKernel = deployBaseURL.JoinPath(ironic.DefaultKernelPath).String()
65+
}
66+
67+
// Set default DeployRamdisk if neither DeployRamdisk nor DeployRamdiskByArch is set
68+
if ir.Spec.DeployRamdisk.DeployRamdisk == "" && ir.Spec.DeployRamdisk.DeployRamdiskByArch == "" {
69+
ir.Spec.DeployRamdisk.DeployRamdisk = deployBaseURL.JoinPath(ironic.DefaultRamdiskPath).String()
70+
}
71+
72+
// Set default probes when using default IPA paths (not multi-arch)
73+
if ir.Spec.DeployRamdisk.DeployKernelByArch == "" && ir.Spec.DeployRamdisk.DeployRamdiskByArch == "" {
74+
defaultProbe := ironic.BuildDefaultHttpdProbe(&ir.Spec)
75+
76+
if ir.Spec.DeployRamdisk.LivenessProbe == nil {
77+
ir.Spec.DeployRamdisk.LivenessProbe = defaultProbe
78+
}
79+
if ir.Spec.DeployRamdisk.ReadinessProbe == nil {
80+
ir.Spec.DeployRamdisk.ReadinessProbe = defaultProbe
81+
}
82+
}
83+
84+
return nil
85+
}
86+
4287
// +kubebuilder:webhook:path=/validate-ironic-metal3-io-v1alpha1-ironic,mutating=false,failurePolicy=fail,sideEffects=None,groups=ironic.metal3.io,resources=ironics,verbs=create;update,versions=v1alpha1,name=validate-ironic.ironic.metal3.io,admissionReviewVersions=v1
4388

4489
type IronicCustomValidator struct{}
4590

4691
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
4792
func (r *IronicCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
48-
ironic, ok := obj.(*metal3api.Ironic)
93+
ir, ok := obj.(*metal3api.Ironic)
4994
if !ok {
5095
return nil, fmt.Errorf("expected an Ironic, got %T", obj)
5196
}
5297

53-
ironiclog.Info("validate create", "name", ironic.Name)
54-
return nil, validation.ValidateIronic(&ironic.Spec, nil)
98+
ironiclog.Info("validate create", "name", ir.Name)
99+
return nil, ironic.ValidateIronic(&ir.Spec, nil)
55100
}
56101

57102
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
58103
func (r *IronicCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
59-
ironic, ok := newObj.(*metal3api.Ironic)
104+
ir, ok := newObj.(*metal3api.Ironic)
60105
if !ok {
61106
return nil, fmt.Errorf("expected an Ironic for newObj, got %T", newObj)
62107
}
63108

64-
oldIronic, ok := oldObj.(*metal3api.Ironic)
109+
oldIr, ok := oldObj.(*metal3api.Ironic)
65110
if !ok {
66111
return nil, fmt.Errorf("expected an Ironic for oldObj, got %T", oldObj)
67112
}
68113

69-
ironiclog.Info("validate update", "name", ironic.Name)
70-
return nil, validation.ValidateIronic(&ironic.Spec, &oldIronic.Spec)
114+
ironiclog.Info("validate update", "name", ir.Name)
115+
return nil, ironic.ValidateIronic(&ir.Spec, &oldIr.Spec)
71116
}
72117

73118
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.

0 commit comments

Comments
 (0)