Skip to content

Commit 5837c1a

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 215bdb2 commit 5837c1a

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
@@ -319,6 +319,16 @@ func (r *CyborgReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
319319

320320
instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage)
321321

322+
//
323+
// Generate agent config secret for dataplane
324+
//
325+
ctrlResult, err := r.ensureAgentConfig(ctx, h, instance, transporturlSecret, inputSecret, acData, keystoneAuthURL, keystoneRegion)
326+
if err != nil {
327+
return ctrl.Result{}, err
328+
} else if (ctrlResult != ctrl.Result{}) {
329+
return ctrlResult, nil
330+
}
331+
322332
//
323333
// Create Keystone Service
324334
//
@@ -348,7 +358,7 @@ func (r *CyborgReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
348358
//
349359
// Create dbsync job
350360
//
351-
ctrlResult, err := r.ensureDBSync(ctx, h, instance, serviceLabels)
361+
ctrlResult, err = r.ensureDBSync(ctx, h, instance, serviceLabels)
352362
if err != nil {
353363
return ctrl.Result{}, err
354364
} else if (ctrlResult != ctrl.Result{}) {
@@ -457,6 +467,10 @@ func (r *CyborgReconciler) initConditions(instance *cyborgv1beta1.Cyborg) error
457467
cyborgv1beta1.CyborgConductorReadyCondition,
458468
condition.InitReason,
459469
cyborgv1beta1.CyborgConductorReadyInitMessage),
470+
condition.UnknownCondition(
471+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
472+
condition.InitReason,
473+
cyborgv1beta1.CyborgAgentConfigReadyInitMessage),
460474
)
461475

462476
instance.Status.Conditions.Init(&cl)
@@ -1173,3 +1187,78 @@ func ensureSecret(
11731187

11741188
return hash, ctrl.Result{}, *s, nil
11751189
}
1190+
1191+
func (r *CyborgReconciler) ensureAgentConfig(
1192+
ctx context.Context,
1193+
h *helper.Helper,
1194+
instance *cyborgv1beta1.Cyborg,
1195+
transporturlSecret corev1.Secret,
1196+
inputSecret corev1.Secret,
1197+
acData *keystonev1.ApplicationCredentialData,
1198+
keystoneAuthURL string,
1199+
keystoneRegion string,
1200+
) (ctrl.Result, error) {
1201+
err := r.generateAgentConfig(ctx, h, instance, transporturlSecret, inputSecret, acData, keystoneAuthURL, keystoneRegion)
1202+
if err != nil {
1203+
instance.Status.Conditions.Set(condition.FalseCondition(
1204+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
1205+
condition.ErrorReason,
1206+
condition.SeverityWarning,
1207+
cyborgv1beta1.CyborgAgentConfigReadyErrorMessage,
1208+
err.Error()))
1209+
return ctrl.Result{}, err
1210+
}
1211+
instance.Status.Conditions.MarkTrue(
1212+
cyborgv1beta1.CyborgAgentConfigReadyCondition, condition.ServiceConfigReadyMessage,
1213+
)
1214+
return ctrl.Result{}, nil
1215+
}
1216+
1217+
func (r *CyborgReconciler) generateAgentConfig(
1218+
ctx context.Context,
1219+
h *helper.Helper,
1220+
instance *cyborgv1beta1.Cyborg,
1221+
transporturlSecret corev1.Secret,
1222+
inputSecret corev1.Secret,
1223+
acData *keystonev1.ApplicationCredentialData,
1224+
keystoneAuthURL string,
1225+
keystoneRegion string,
1226+
) error {
1227+
servicePassword := string(inputSecret.Data[instance.Spec.PasswordSelectors.Service])
1228+
1229+
templateParameters := map[string]any{
1230+
"TransportURL": string(transporturlSecret.Data[TransportURLSelector]),
1231+
"QuorumQueues": string(transporturlSecret.Data[QuorumQueuesSelector]) == "true",
1232+
"KeystoneAuthURL": keystoneAuthURL,
1233+
"ServiceUser": *instance.Spec.ServiceUser,
1234+
"ServicePassword": servicePassword,
1235+
"Region": keystoneRegion,
1236+
}
1237+
1238+
if acData != nil {
1239+
templateParameters["ACID"] = acData.ID
1240+
templateParameters["ACSecret"] = acData.Secret
1241+
}
1242+
1243+
if instance.Spec.APIServiceTemplate.TLS.CaBundleSecretName != "" {
1244+
templateParameters["CaFilePath"] = tls.DownstreamTLSCABundlePath
1245+
}
1246+
1247+
serviceLabels := labels.GetLabels(instance, labels.GetGroupLabel(cyborgservice.ServiceName), map[string]string{})
1248+
1249+
cms := []util.Template{
1250+
{
1251+
Name: instance.GetName() + "-agent-config",
1252+
Namespace: instance.GetNamespace(),
1253+
Type: util.TemplateTypeConfig,
1254+
InstanceType: instance.GetObjectKind().GroupVersionKind().Kind,
1255+
ConfigOptions: templateParameters,
1256+
Labels: serviceLabels,
1257+
AdditionalTemplate: map[string]string{
1258+
"00-default.conf": "/cyborg/00-default.conf",
1259+
},
1260+
},
1261+
}
1262+
1263+
return secret.EnsureSecrets(ctx, h, instance, cms, nil)
1264+
}

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)
@@ -311,6 +343,13 @@ var _ = Describe("Cyborg controller", func() {
311343
corev1.ConditionTrue,
312344
)
313345

346+
th.ExpectCondition(
347+
cyborgNames.CyborgName,
348+
ConditionGetterFunc(CyborgConditionGetter),
349+
cyborgv1beta1.CyborgAgentConfigReadyCondition,
350+
corev1.ConditionTrue,
351+
)
352+
314353
keystone.SimulateKeystoneServiceReady(cyborgNames.KeystoneServiceName)
315354

316355
th.ExpectCondition(
@@ -437,6 +476,23 @@ var _ = Describe("Cyborg controller", func() {
437476
)
438477
})
439478

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