Skip to content

Commit 7c239f1

Browse files
committed
cyborg: Generate agent config secret for dataplane deployment
The Cyborg controller now generates a `{name}-agent-config` secret containing the rendered configuration for the cyborg-agent service running on EDPM compute nodes. This secret is consumed by the edpm-ansible cyborg role to configure the agent on the dataplane. The shared 00-default.conf template is updated to guard the [database] section with a conditional, allowing reuse for the agent config without a separate template. Assisted-By: claude Signed-off-by: Alfredo Moralejo <amoralej@redhat.com>
1 parent 68342cb commit 7c239f1

5 files changed

Lines changed: 174 additions & 1 deletion

File tree

api/cyborg/v1beta1/conditions.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ const (
3232

3333
// CyborgConductorReadyCondition indicates whether the CyborgConductor is ready
3434
CyborgConductorReadyCondition condition.Type = "CyborgConductorReady"
35+
36+
// CyborgAgentConfigReadyCondition indicates whether the Cyborg agent config secret is ready
37+
CyborgAgentConfigReadyCondition condition.Type = "CyborgAgentConfigReady"
3538
)
3639

3740
const (
@@ -58,4 +61,10 @@ const (
5861

5962
// CyborgApplicationCredentialSecretErrorMessage -
6063
CyborgApplicationCredentialSecretErrorMessage = "Error with application credential secret"
64+
65+
// CyborgAgentConfigReadyInitMessage -
66+
CyborgAgentConfigReadyInitMessage = "CyborgAgent config not started"
67+
68+
// CyborgAgentConfigReadyErrorMessage -
69+
CyborgAgentConfigReadyErrorMessage = "CyborgAgent config error occurred %s"
6170
)

internal/controller/cyborg/cyborg_controller.go

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,16 @@ func (r *CyborgReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
337337

338338
instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage)
339339

340+
//
341+
// Generate agent config secret for dataplane
342+
//
343+
ctrlResult, err := r.ensureAgentConfig(ctx, h, instance, transporturlSecret, inputSecret, acData, keystoneAuthURL, keystoneRegion)
344+
if err != nil {
345+
return ctrl.Result{}, err
346+
} else if (ctrlResult != ctrl.Result{}) {
347+
return ctrlResult, nil
348+
}
349+
340350
//
341351
// Create Keystone Service
342352
//
@@ -366,7 +376,7 @@ func (r *CyborgReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
366376
//
367377
// Create dbsync job
368378
//
369-
ctrlResult, err := r.ensureDBSync(ctx, h, instance, serviceLabels)
379+
ctrlResult, err = r.ensureDBSync(ctx, h, instance, serviceLabels)
370380
if err != nil {
371381
return ctrl.Result{}, err
372382
} else if (ctrlResult != ctrl.Result{}) {
@@ -494,6 +504,10 @@ func (r *CyborgReconciler) initConditions(instance *cyborgv1beta1.Cyborg) error
494504
cyborgv1beta1.CyborgConductorReadyCondition,
495505
condition.InitReason,
496506
cyborgv1beta1.CyborgConductorReadyInitMessage),
507+
condition.UnknownCondition(
508+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
509+
condition.InitReason,
510+
cyborgv1beta1.CyborgAgentConfigReadyInitMessage),
497511
)
498512

499513
instance.Status.Conditions.Init(&cl)
@@ -1221,3 +1235,78 @@ func ensureSecret(
12211235

12221236
return hash, ctrl.Result{}, *s, nil
12231237
}
1238+
1239+
func (r *CyborgReconciler) ensureAgentConfig(
1240+
ctx context.Context,
1241+
h *helper.Helper,
1242+
instance *cyborgv1beta1.Cyborg,
1243+
transporturlSecret corev1.Secret,
1244+
inputSecret corev1.Secret,
1245+
acData *keystonev1.ApplicationCredentialData,
1246+
keystoneAuthURL string,
1247+
keystoneRegion string,
1248+
) (ctrl.Result, error) {
1249+
err := r.generateAgentConfig(ctx, h, instance, transporturlSecret, inputSecret, acData, keystoneAuthURL, keystoneRegion)
1250+
if err != nil {
1251+
instance.Status.Conditions.Set(condition.FalseCondition(
1252+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
1253+
condition.ErrorReason,
1254+
condition.SeverityWarning,
1255+
cyborgv1beta1.CyborgAgentConfigReadyErrorMessage,
1256+
err.Error()))
1257+
return ctrl.Result{}, err
1258+
}
1259+
instance.Status.Conditions.MarkTrue(
1260+
cyborgv1beta1.CyborgAgentConfigReadyCondition, condition.ServiceConfigReadyMessage,
1261+
)
1262+
return ctrl.Result{}, nil
1263+
}
1264+
1265+
func (r *CyborgReconciler) generateAgentConfig(
1266+
ctx context.Context,
1267+
h *helper.Helper,
1268+
instance *cyborgv1beta1.Cyborg,
1269+
transporturlSecret corev1.Secret,
1270+
inputSecret corev1.Secret,
1271+
acData *keystonev1.ApplicationCredentialData,
1272+
keystoneAuthURL string,
1273+
keystoneRegion string,
1274+
) error {
1275+
servicePassword := string(inputSecret.Data[instance.Spec.PasswordSelectors.Service])
1276+
1277+
templateParameters := map[string]any{
1278+
"TransportURL": string(transporturlSecret.Data[TransportURLSelector]),
1279+
"QuorumQueues": string(transporturlSecret.Data[QuorumQueuesSelector]) == "true",
1280+
"KeystoneAuthURL": keystoneAuthURL,
1281+
"ServiceUser": *instance.Spec.ServiceUser,
1282+
"ServicePassword": servicePassword,
1283+
"Region": keystoneRegion,
1284+
}
1285+
1286+
if acData != nil {
1287+
templateParameters["ACID"] = acData.ID
1288+
templateParameters["ACSecret"] = acData.Secret
1289+
}
1290+
1291+
if instance.Spec.APIServiceTemplate.TLS.CaBundleSecretName != "" {
1292+
templateParameters["CaFilePath"] = tls.DownstreamTLSCABundlePath
1293+
}
1294+
1295+
serviceLabels := labels.GetLabels(instance, labels.GetGroupLabel(cyborgservice.ServiceName), map[string]string{})
1296+
1297+
cms := []util.Template{
1298+
{
1299+
Name: instance.GetName() + "-agent-config",
1300+
Namespace: instance.GetNamespace(),
1301+
Type: util.TemplateTypeConfig,
1302+
InstanceType: instance.GetObjectKind().GroupVersionKind().Kind,
1303+
ConfigOptions: templateParameters,
1304+
Labels: serviceLabels,
1305+
AdditionalTemplate: map[string]string{
1306+
"00-default.conf": "/cyborg/00-default.conf",
1307+
},
1308+
},
1309+
}
1310+
1311+
return secret.EnsureSecrets(ctx, h, instance, cms, nil)
1312+
}

templates/cyborg/00-default.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ transport_url = {{ .TransportURL }}
88
log_file = {{ .LogFile }}
99
{{ end }}
1010

11+
{{ if (index . "DatabaseConnection") }}
1112
[database]
1213
connection = {{ .DatabaseConnection }}
14+
{{ end }}
1315

1416
{{ if (index . "TransportURL") }}
1517
[oslo_messaging_rabbit]

test/functional/cyborg/cyborg_controller_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type CyborgNames struct {
6767
ConductorName types.NamespacedName
6868
ConductorStatefulSetName types.NamespacedName
6969
ConductorConfigDataName types.NamespacedName
70+
AgentConfigSecretName types.NamespacedName
7071
}
7172

7273
func GetCyborgNames(cyborgName types.NamespacedName) CyborgNames {
@@ -140,6 +141,10 @@ func GetCyborgNames(cyborgName types.NamespacedName) CyborgNames {
140141
Namespace: cyborgName.Namespace,
141142
Name: cyborgName.Name + "-conductor-config-data",
142143
},
144+
AgentConfigSecretName: types.NamespacedName{
145+
Namespace: cyborgName.Namespace,
146+
Name: cyborgName.Name + "-agent-config",
147+
},
143148
}
144149
}
145150

@@ -164,6 +169,7 @@ var _ = Describe("Cyborg controller", func() {
164169
g.Expect(cyborg.Status.Conditions.Has(condition.DBSyncReadyCondition)).To(BeTrue())
165170
g.Expect(cyborg.Status.Conditions.Has(condition.KeystoneServiceReadyCondition)).To(BeTrue())
166171
g.Expect(cyborg.Status.Conditions.Has(cyborgv1beta1.CyborgAPIReadyCondition)).To(BeTrue())
172+
g.Expect(cyborg.Status.Conditions.Has(cyborgv1beta1.CyborgAgentConfigReadyCondition)).To(BeTrue())
167173
}, timeout, interval).Should(Succeed())
168174
})
169175

@@ -274,6 +280,32 @@ var _ = Describe("Cyborg controller", func() {
274280
}, timeout, interval).Should(Succeed())
275281
})
276282

283+
It("creates an agent config secret for the dataplane", func() {
284+
mariadb.SimulateMariaDBAccountCompleted(cyborgNames.MariaDBAccountName)
285+
mariadb.SimulateMariaDBDatabaseCompleted(cyborgNames.MariaDBDatabaseName)
286+
infra.SimulateTransportURLReady(cyborgNames.TransportURLName)
287+
288+
Eventually(func(g Gomega) {
289+
agentSecret := th.GetSecret(cyborgNames.AgentConfigSecretName)
290+
g.Expect(agentSecret.Data).To(HaveKey("00-default.conf"))
291+
292+
defaultConf := string(agentSecret.Data["00-default.conf"])
293+
g.Expect(defaultConf).To(ContainSubstring("transport_url"))
294+
g.Expect(defaultConf).To(ContainSubstring("[keystone_authtoken]"))
295+
g.Expect(defaultConf).To(ContainSubstring("[placement]"))
296+
g.Expect(defaultConf).To(ContainSubstring("[nova]"))
297+
g.Expect(defaultConf).To(ContainSubstring("username = cyborg"))
298+
g.Expect(defaultConf).NotTo(ContainSubstring("[database]"))
299+
}, timeout, interval).Should(Succeed())
300+
301+
th.ExpectCondition(
302+
cyborgNames.CyborgName,
303+
ConditionGetterFunc(CyborgConditionGetter),
304+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
305+
corev1.ConditionTrue,
306+
)
307+
})
308+
277309
It("creates a config data secret for dbsync", func() {
278310
mariadb.SimulateMariaDBAccountCompleted(cyborgNames.MariaDBAccountName)
279311
mariadb.SimulateMariaDBDatabaseCompleted(cyborgNames.MariaDBDatabaseName)
@@ -314,6 +346,13 @@ var _ = Describe("Cyborg controller", func() {
314346
corev1.ConditionTrue,
315347
)
316348

349+
th.ExpectCondition(
350+
cyborgNames.CyborgName,
351+
ConditionGetterFunc(CyborgConditionGetter),
352+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
353+
corev1.ConditionTrue,
354+
)
355+
317356
keystone.SimulateKeystoneServiceReady(cyborgNames.KeystoneServiceName)
318357

319358
th.ExpectCondition(
@@ -440,6 +479,23 @@ var _ = Describe("Cyborg controller", func() {
440479
)
441480
})
442481

482+
It("creates an agent config secret with application credentials and TLS CA", func() {
483+
mariadb.SimulateMariaDBAccountCompleted(cyborgNames.MariaDBAccountName)
484+
mariadb.SimulateMariaDBTLSDatabaseCompleted(cyborgNames.MariaDBDatabaseName)
485+
infra.SimulateTransportURLReady(cyborgNames.TransportURLName)
486+
487+
Eventually(func(g Gomega) {
488+
agentSecret := th.GetSecret(cyborgNames.AgentConfigSecretName)
489+
defaultConf := string(agentSecret.Data["00-default.conf"])
490+
g.Expect(defaultConf).To(ContainSubstring("auth_type = v3applicationcredential"))
491+
g.Expect(defaultConf).To(ContainSubstring("application_credential_id = " + appCredID))
492+
g.Expect(defaultConf).To(ContainSubstring("application_credential_secret = " + appCredSecretValue))
493+
g.Expect(defaultConf).To(ContainSubstring("cafile ="))
494+
g.Expect(defaultConf).To(ContainSubstring("ssl_ca_file ="))
495+
g.Expect(defaultConf).NotTo(ContainSubstring("[database]"))
496+
}, timeout, interval).Should(Succeed())
497+
})
498+
443499
It("creates dbsync job, TLS-aware config secret, and application credential data in the sub-level secret", func() {
444500
mariadb.SimulateMariaDBAccountCompleted(cyborgNames.MariaDBAccountName)
445501
mariadb.SimulateMariaDBTLSDatabaseCompleted(cyborgNames.MariaDBDatabaseName)

test/kuttl/test-suites/default/cyborg-tests/01-assert.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ commands:
4040
- script: |
4141
oc get secret cyborg-kuttl-conductor-config-data -n $NAMESPACE \
4242
-o jsonpath='{.data.cyborg-conductor-config\.json}' | base64 -d | grep -q 'cyborg-conductor'
43+
# --- Cyborg agent config secret (cyborg-kuttl-agent-config) content ---
44+
# 00-default.conf must contain the [DEFAULT] OpenStack config section
45+
- script: |
46+
oc get secret cyborg-kuttl-agent-config -n $NAMESPACE \
47+
-o jsonpath='{.data.00-default\.conf}' | base64 -d | grep -q '\[DEFAULT\]'
4348
# --- DB sync Job volumes ---
4449
# config-data volume in the Job pod must reference the Cyborg config-data secret
4550
- script: |
@@ -112,6 +117,10 @@ status:
112117
reason: Ready
113118
status: "True"
114119
type: CyborgAPIReady
120+
- message: Service config create completed
121+
reason: Ready
122+
status: "True"
123+
type: CyborgAgentConfigReady
115124
- message: Deployment completed
116125
reason: Ready
117126
status: "True"
@@ -486,3 +495,11 @@ status:
486495
- name: cyborg-conductor
487496
ready: true
488497
started: true
498+
---
499+
# Assert the Cyborg agent config-data secret exists.
500+
# Expected files: 00-default.conf
501+
# Content checks are performed via the commands block above.
502+
apiVersion: v1
503+
kind: Secret
504+
metadata:
505+
name: cyborg-kuttl-agent-config

0 commit comments

Comments
 (0)