Skip to content
Merged
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
38 changes: 38 additions & 0 deletions controllers/ironic_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ import (

k8s_errors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -228,9 +232,43 @@ func (r *IronicReconciler) SetupWithManager(mgr ctrl.Manager) error {
Owns(&corev1.ServiceAccount{}).
Owns(&rbacv1.Role{}).
Owns(&rbacv1.RoleBinding{}).
Watches(&keystonev1.KeystoneAPI{},
handler.EnqueueRequestsFromMapFunc(r.findObjectForSrc),
builder.WithPredicates(keystonev1.KeystoneAPIStatusChangedPredicate)).
Complete(r)
}

func (r *IronicReconciler) findObjectForSrc(ctx context.Context, src client.Object) []reconcile.Request {
requests := []reconcile.Request{}

l := log.FromContext(ctx).WithName("Controllers").WithName("Ironic")

crList := &ironicv1.IronicList{}
listOps := &client.ListOptions{
Namespace: src.GetNamespace(),
}
err := r.Client.List(ctx, crList, listOps)
if err != nil {
l.Error(err, fmt.Sprintf("listing %s for namespace: %s", crList.GroupVersionKind().Kind, src.GetNamespace()))
return requests
}

for _, item := range crList.Items {
l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace()))

requests = append(requests,
reconcile.Request{
NamespacedName: types.NamespacedName{
Name: item.GetName(),
Namespace: item.GetNamespace(),
},
},
)
}

return requests
}

func (r *IronicReconciler) reconcileDelete(ctx context.Context, instance *ironicv1.Ironic, helper *helper.Helper) (ctrl.Result, error) {
Log := r.GetLogger(ctx)

Expand Down
35 changes: 35 additions & 0 deletions controllers/ironicinspector_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
routev1 "github.com/openshift/api/route/v1"
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/types"
k8s_types "k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"

Expand Down Expand Up @@ -384,6 +385,9 @@ func (r *IronicInspectorReconciler) SetupWithManager(
Watches(&topologyv1.Topology{},
handler.EnqueueRequestsFromMapFunc(r.findObjectsForSrc),
builder.WithPredicates(predicate.GenerationChangedPredicate{})).
Watches(&keystonev1.KeystoneAPI{},
handler.EnqueueRequestsFromMapFunc(r.findObjectForSrc),
builder.WithPredicates(keystonev1.KeystoneAPIStatusChangedPredicate)).
Complete(r)
}

Expand Down Expand Up @@ -421,6 +425,37 @@ func (r *IronicInspectorReconciler) findObjectsForSrc(ctx context.Context, src c
return requests
}

func (r *IronicInspectorReconciler) findObjectForSrc(ctx context.Context, src client.Object) []reconcile.Request {
requests := []reconcile.Request{}

l := log.FromContext(ctx).WithName("Controllers").WithName("IronicInspector")

crList := &ironicv1.IronicInspectorList{}
listOps := &client.ListOptions{
Namespace: src.GetNamespace(),
}
err := r.Client.List(ctx, crList, listOps)
if err != nil {
l.Error(err, fmt.Sprintf("listing %s for namespace: %s", crList.GroupVersionKind().Kind, src.GetNamespace()))
return requests
}

for _, item := range crList.Items {
l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace()))

requests = append(requests,
reconcile.Request{
NamespacedName: types.NamespacedName{
Name: item.GetName(),
Namespace: item.GetNamespace(),
},
},
)
}

return requests
}

func (r *IronicInspectorReconciler) getTransportURL(
ctx context.Context,
h *helper.Helper,
Expand Down
34 changes: 34 additions & 0 deletions controllers/ironicneutronagent_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ func (r *IronicNeutronAgentReconciler) SetupWithManager(
Watches(&topologyv1.Topology{},
handler.EnqueueRequestsFromMapFunc(r.findObjectsForSrc),
builder.WithPredicates(predicate.GenerationChangedPredicate{})).
Watches(&keystonev1.KeystoneAPI{},
handler.EnqueueRequestsFromMapFunc(r.findObjectForSrc),
builder.WithPredicates(keystonev1.KeystoneAPIStatusChangedPredicate)).
Complete(r)
}

Expand Down Expand Up @@ -317,6 +320,37 @@ func (r *IronicNeutronAgentReconciler) findObjectsForSrc(ctx context.Context, sr
return requests
}

func (r *IronicNeutronAgentReconciler) findObjectForSrc(ctx context.Context, src client.Object) []reconcile.Request {
requests := []reconcile.Request{}

l := log.FromContext(ctx).WithName("Controllers").WithName("IronicNeutronAgent")

crList := &ironicv1.IronicNeutronAgentList{}
listOps := &client.ListOptions{
Namespace: src.GetNamespace(),
}
err := r.Client.List(ctx, crList, listOps)
if err != nil {
l.Error(err, fmt.Sprintf("listing %s for namespace: %s", crList.GroupVersionKind().Kind, src.GetNamespace()))
return requests
}

for _, item := range crList.Items {
l.Info(fmt.Sprintf("input source %s changed, reconcile: %s - %s", src.GetName(), item.GetName(), item.GetNamespace()))

requests = append(requests,
reconcile.Request{
NamespacedName: types.NamespacedName{
Name: item.GetName(),
Namespace: item.GetNamespace(),
},
},
)
}

return requests
}

func (r *IronicNeutronAgentReconciler) getTransportURL(
ctx context.Context,
h *helper.Helper,
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/openshift/api v3.9.0+incompatible
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250513115636-b549982a5d8f
github.com/openstack-k8s-operators/ironic-operator/api v0.0.0-00010101000000-000000000000
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250521085253-60910fbce943
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250604143452-2260c431b9f1
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250508141203-be026d3164f7
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20250508141203-be026d3164f7
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20250521084122-c6dc1ca7ed7c
Expand Down Expand Up @@ -54,8 +54,8 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20250423055245-3cb2ae8df6f0 // indirect
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250423055245-3cb2ae8df6f0 // indirect
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20250508141203-be026d3164f7 // indirect
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250508141203-be026d3164f7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.19.0 // indirect
github.com/prometheus/client_model v0.6.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 h1:J1wuGhVxpsHykZBa6
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250513115636-b549982a5d8f h1:b3WGatQCIBoNj8RvbVGNITL9RuQLwkXzXAgt7s/D5zc=
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20250513115636-b549982a5d8f/go.mod h1:47iJk3vedZWnBkZyNyYij4ma2HjG4l2VCqKz3f+XDkQ=
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250521085253-60910fbce943 h1:FbalBf7TrezrxTQYHBGCGqx9ZZl6rLKuCap30sp4LYg=
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250521085253-60910fbce943/go.mod h1:zaXbveCF80JXvRUuoXAXFXFMCbsiERvtyVoE0lpfTJ0=
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250604143452-2260c431b9f1 h1:YQuJwgoQ9mEyzNq9/SgS3wPCtLG0wMQWH/caWAMZeSc=
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20250604143452-2260c431b9f1/go.mod h1:dgYQJbbVaRuP98yZZB3K1rNpqnF54I1HM1ZTaOzPKBY=
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250508141203-be026d3164f7 h1:c3h1q3fDoit3NmvNL89xUL9A12bJivaTF+IOPEOAwLc=
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20250508141203-be026d3164f7/go.mod h1:UwHXRIrMSPJD3lFqrA4oKmRXVLFQCRkLAj9x6KLEHiQ=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20250423055245-3cb2ae8df6f0 h1:FAHrScvlj6w17wvcDhJ0ZnmraMrrOX1CxzvqZK595hA=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20250423055245-3cb2ae8df6f0/go.mod h1:fesgTbs2j30Fhw2hebXkPgbeAIqG0Yk2oaeOklAInZg=
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250423055245-3cb2ae8df6f0 h1:JejCQvZ28JmG87iGpy0tk8v4WJzZ07PIIAxXRpiMR9E=
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250423055245-3cb2ae8df6f0/go.mod h1:5+v92XC/PRATIiBrhNLEpJ+T4R9JpxBCgRP6QvbfwgE=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20250508141203-be026d3164f7 h1:IybBq3PrxwdvzAF19TjdMCqbEVkX2p3gIkme/Fju6do=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20250508141203-be026d3164f7/go.mod h1:fesgTbs2j30Fhw2hebXkPgbeAIqG0Yk2oaeOklAInZg=
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250508141203-be026d3164f7 h1:N7HNoUrjqrWZWWcQdtaZubrQ1pFeWai1Cbls0RoCjK8=
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250508141203-be026d3164f7/go.mod h1:5+v92XC/PRATIiBrhNLEpJ+T4R9JpxBCgRP6QvbfwgE=
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20250508141203-be026d3164f7 h1:SiJ+T5OK5y4dkPFvHZZeLpSHjDFULaaGKZ2dFdE8uRg=
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20250508141203-be026d3164f7/go.mod h1:oKvVb28i6wwBR5uQO2B2KMzZnCFTPCUCj31c5Zvz2lo=
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20250521084122-c6dc1ca7ed7c h1:8IysMuJ8t37aBts1N04i1mkWOJNIfzBZHkkJjNkZy5g=
Expand Down
5 changes: 5 additions & 0 deletions tests/functional/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type IronicNames struct {
InspectorConfigSecretName types.NamespacedName
INAName types.NamespacedName
INATransportURLName types.NamespacedName
INAConfigSecretName types.NamespacedName
KeystoneServiceName types.NamespacedName
InternalCertSecretName types.NamespacedName
PublicCertSecretName types.NamespacedName
Expand Down Expand Up @@ -233,6 +234,10 @@ func GetIronicNames(
Namespace: ironicNeutronAgent.Namespace,
Name: ironicNeutronAgent.Name + "-transport",
},
INAConfigSecretName: types.NamespacedName{
Namespace: ironicNeutronAgent.Namespace,
Name: "ironic-ironic-neutron-agent-config-data",
},
InternalCertSecretName: types.NamespacedName{
Namespace: ironicName.Namespace,
Name: "internal-tls-certs",
Expand Down
103 changes: 103 additions & 0 deletions tests/functional/ironic_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,109 @@ var _ = Describe("Ironic controller", func() {

})

Context("Ironic is fully deployed", func() {
keystoneAPIName := types.NamespacedName{}
BeforeEach(func() {
DeferCleanup(
k8sClient.Delete,
ctx,
CreateIronicSecret(ironicNames.Namespace, SecretName),
)
DeferCleanup(
k8sClient.Delete,
ctx,
CreateMessageBusSecret(ironicNames.Namespace, MessageBusSecretName),
)

apiMariaDBAccount, apiMariaDBSecret := mariadb.CreateMariaDBAccountAndSecret(ironicNames.IronicDatabaseAccount, mariadbv1.MariaDBAccountSpec{})
DeferCleanup(k8sClient.Delete, ctx, apiMariaDBAccount)
DeferCleanup(k8sClient.Delete, ctx, apiMariaDBSecret)
DeferCleanup(
mariadb.DeleteDBService,
mariadb.CreateDBService(
ironicNames.Namespace,
"openstack",
corev1.ServiceSpec{
Ports: []corev1.ServicePort{{Port: 3306}},
},
),
)
keystoneAPIName = keystone.CreateKeystoneAPI(ironicNames.Namespace)
DeferCleanup(
keystone.DeleteKeystoneAPI,
keystoneAPIName)
DeferCleanup(
th.DeleteInstance,
CreateIronic(ironicNames.IronicName, GetDefaultIronicSpec()),
)
mariadb.GetMariaDBDatabase(ironicNames.IronicDatabaseName)
mariadb.SimulateMariaDBAccountCompleted(ironicNames.IronicDatabaseAccount)
mariadb.SimulateMariaDBDatabaseCompleted(ironicNames.IronicDatabaseName)
th.SimulateJobSuccess(ironicNames.IronicDBSyncJobName)

keystone.SimulateKeystoneServiceReady(ironicNames.IronicName)
keystone.SimulateKeystoneEndpointReady(ironicNames.IronicName)

mariadb.GetMariaDBDatabase(ironicNames.InspectorDatabaseName)
mariadb.SimulateMariaDBAccountCompleted(ironicNames.InspectorDatabaseAccount)
mariadb.SimulateMariaDBDatabaseCompleted(ironicNames.InspectorDatabaseName)
th.SimulateJobSuccess(ironicNames.InspectorDBSyncJobName)

nestedINATransportURLName := ironicNames.INATransportURLName
nestedINATransportURLName.Name = ironicNames.IronicName.Name + "-" + nestedINATransportURLName.Name
infra.GetTransportURL(nestedINATransportURLName)
infra.SimulateTransportURLReady(nestedINATransportURLName)

th.SimulateDeploymentReplicaReady(ironicNames.IronicName)
th.SimulateStatefulSetReplicaReady(ironicNames.ConductorName)
th.SimulateStatefulSetReplicaReady(ironicNames.InspectorName)
keystone.SimulateKeystoneServiceReady(ironicNames.InspectorName)
keystone.SimulateKeystoneEndpointReady(ironicNames.InspectorName)
th.SimulateDeploymentReplicaReady(ironicNames.INAName)

th.ExpectCondition(
ironicNames.IronicName,
ConditionGetterFunc(IronicConditionGetter),
condition.ReadyCondition,
corev1.ConditionTrue,
)
})

It("updates the KeystoneAuthURL if keystone internal endpoint changes", func() {
newInternalEndpoint := "https://keystone-internal"

keystone.UpdateKeystoneAPIEndpoint(keystoneAPIName, "internal", newInternalEndpoint)
logger.Info("Reconfigured")

Eventually(func(g Gomega) {
confSecret := th.GetSecret(ironicNames.IronicConfigSecretName)
g.Expect(confSecret).ShouldNot(BeNil())

conf := confSecret.Data["ironic.conf"]
g.Expect(string(conf)).Should(
ContainSubstring("auth_url=%s", newInternalEndpoint))
}, timeout, interval).Should(Succeed())

Eventually(func(g Gomega) {
confSecret := th.GetSecret(ironicNames.InspectorConfigSecretName)
g.Expect(confSecret).ShouldNot(BeNil())

conf := confSecret.Data["01-inspector.conf"]
g.Expect(string(conf)).Should(
ContainSubstring("auth_url=%s", newInternalEndpoint))
}, timeout, interval).Should(Succeed())

Eventually(func(g Gomega) {
confSecret := th.GetSecret(ironicNames.INAConfigSecretName)
g.Expect(confSecret).ShouldNot(BeNil())

conf := confSecret.Data["01-ironic_neutron_agent.conf"]
g.Expect(string(conf)).Should(
ContainSubstring("auth_url=%s", newInternalEndpoint))
}, timeout, interval).Should(Succeed())
})
})

When("Ironic is created with topologyref", func() {
var topologyRef, topologyRefAlt *topologyv1.TopoRef
BeforeEach(func() {
Expand Down