Skip to content

Commit 0634aec

Browse files
MGMT-19496: Always reconcile ignition token secret (#157)
The secret used as the bearer token for the ignition server should always be updated or created regardless of the status of the AgentMachine. This is to prevent scenarios where the secret is deleted but not recreated when an AgentMachine is ready. Co-authored-by: CrystalChun <[email protected]>
1 parent 77d1c08 commit 0634aec

File tree

2 files changed

+112
-6
lines changed

2 files changed

+112
-6
lines changed

controllers/agentmachine_controller.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ func (r *AgentMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request
132132
return ctrl.Result{}, nil
133133
}
134134

135+
machineConfigPool, ignitionTokenSecretRef, ignitionEndpointHTTPHeaders, err := r.processBootstrapDataSecret(ctx, log, machine, agentMachine.Status.Ready)
136+
if err != nil {
137+
return ctrl.Result{}, err
138+
}
139+
135140
// If the AgentMachine is ready, we have nothing to do
136141
if agentMachine.Status.Ready {
137142
return ctrl.Result{}, nil
@@ -148,11 +153,6 @@ func (r *AgentMachineReconciler) Reconcile(ctx context.Context, req ctrl.Request
148153
return ctrl.Result{}, r.updateStatus(ctx, log, agentMachine, err)
149154
}
150155

151-
machineConfigPool, ignitionTokenSecretRef, ignitionEndpointHTTPHeaders, err := r.processBootstrapDataSecret(ctx, log, machine)
152-
if err != nil {
153-
return ctrl.Result{}, err
154-
}
155-
156156
// If the AgentMachine doesn't have an agent, find one and set the agentRef
157157
if agentMachine.Status.AgentRef == nil {
158158
var foundAgent *aiv1beta1.Agent
@@ -439,7 +439,7 @@ func (r *AgentMachineReconciler) updateFoundAgent(ctx context.Context, log logru
439439
}
440440

441441
func (r *AgentMachineReconciler) processBootstrapDataSecret(ctx context.Context, log logrus.FieldLogger,
442-
machine *clusterv1.Machine) (string, *aiv1beta1.IgnitionEndpointTokenReference, map[string]string, error) {
442+
machine *clusterv1.Machine, agentMachineReady bool) (string, *aiv1beta1.IgnitionEndpointTokenReference, map[string]string, error) {
443443

444444
machineConfigPool := ""
445445
var ignitionTokenSecretRef *aiv1beta1.IgnitionEndpointTokenReference
@@ -505,6 +505,9 @@ func (r *AgentMachineReconciler) processBootstrapDataSecret(ctx context.Context,
505505
ignitionTokenSecretRef = &aiv1beta1.IgnitionEndpointTokenReference{Namespace: machine.Namespace, Name: ignitionTokenSecretName}
506506
// TODO: Use a dedicated secret per host and Delete the secret upon cleanup,
507507
err := r.Client.Create(ctx, ignitionTokenSecret)
508+
if err == nil && agentMachineReady {
509+
log.Warnf("ignition token secret %s should not be deleted", ignitionTokenSecret)
510+
}
508511
if apierrors.IsAlreadyExists(err) {
509512
log.Infof("ignitionTokenSecret %s already exists, updating secret content",
510513
fmt.Sprintf("agent-%s", *machine.Spec.Bootstrap.DataSecretName))

controllers/agentmachine_controller_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,109 @@ var _ = Describe("agentmachine reconcile", func() {
667667
Expect(agent.Spec.ClusterDeploymentName.Name).To(BeEquivalentTo("cluster-deployment-agentMachine-1"))
668668
})
669669
})
670+
Context("reconciling ignition token secret", func() {
671+
var (
672+
agent *aiv1beta1.Agent
673+
agentMachine *capiproviderv1.AgentMachine
674+
machine *clusterv1.Machine
675+
)
676+
677+
BeforeEach(func() {
678+
agent = newAgent("agent-1", testNamespace, aiv1beta1.AgentSpec{Approved: false})
679+
agent.Status.Conditions = append(agent.Status.Conditions, v1.Condition{Type: aiv1beta1.BoundCondition, Status: "True"})
680+
agent.Status.Conditions = append(agent.Status.Conditions, v1.Condition{Type: aiv1beta1.ValidatedCondition, Status: "True"})
681+
agent.Spec.ClusterDeploymentName = &aiv1beta1.ClusterReference{Name: "cluster-deployment-agentMachine-1", Namespace: testNamespace}
682+
agentMachine, machine = newAgentMachine("agentMachine-1", testNamespace, capiproviderv1.AgentMachineSpec{}, ctx, c)
683+
684+
Expect(c.Create(ctx, agent)).To(BeNil())
685+
Expect(c.Create(ctx, agentMachine)).To(BeNil())
686+
})
687+
AfterEach(func() {
688+
mockCtrl.Finish()
689+
})
690+
It("creates the ignition token secret upon first reconcile of an AgentMachine", func() {
691+
result, err := amr.Reconcile(ctx, newAgentMachineRequest(agentMachine))
692+
Expect(err).To(BeNil())
693+
Expect(result).To(Equal(ctrl.Result{}))
694+
695+
ignitionTokenSecretName := machine.Spec.Bootstrap.DataSecretName
696+
ignitionTokenSecret := &corev1.Secret{}
697+
Expect(c.Get(ctx, types.NamespacedName{Name: *ignitionTokenSecretName, Namespace: testNamespace}, ignitionTokenSecret)).To(Succeed())
698+
ignitionConfig := &ignitionapi.Config{}
699+
Expect(json.Unmarshal(ignitionTokenSecret.Data["value"], ignitionConfig)).To(Succeed())
700+
expectedPrefix := "Bearer "
701+
ignitionToken := (*ignitionConfig.Ignition.Config.Merge[0].HTTPHeaders[0].Value)[len(expectedPrefix):]
702+
703+
agentSecret := &corev1.Secret{}
704+
Expect(c.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("agent-%s", *ignitionTokenSecretName), Namespace: testNamespace}, agentSecret)).To(Succeed())
705+
Expect(agentSecret.Data).NotTo(BeEmpty())
706+
Expect(agentSecret.Data).To(HaveKey("ignition-token"))
707+
Expect(string(agentSecret.Data["ignition-token"])).To(Equal(ignitionToken))
708+
})
709+
It("updates the ignition token secret if the token changed", func() {
710+
result, err := amr.Reconcile(ctx, newAgentMachineRequest(agentMachine))
711+
Expect(err).To(BeNil())
712+
Expect(result).To(Equal(ctrl.Result{}))
713+
714+
ignitionTokenSecretName := machine.Spec.Bootstrap.DataSecretName
715+
ignitionTokenSecret := &corev1.Secret{}
716+
Expect(c.Get(ctx, types.NamespacedName{Name: *ignitionTokenSecretName, Namespace: testNamespace}, ignitionTokenSecret)).To(Succeed())
717+
ignitionConfig := &ignitionapi.Config{}
718+
Expect(json.Unmarshal(ignitionTokenSecret.Data["value"], ignitionConfig)).To(Succeed())
719+
expectedPrefix := "Bearer "
720+
ignitionToken := (*ignitionConfig.Ignition.Config.Merge[0].HTTPHeaders[0].Value)[len(expectedPrefix):]
721+
722+
agentSecret := &corev1.Secret{}
723+
Expect(c.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("agent-%s", *ignitionTokenSecretName), Namespace: testNamespace}, agentSecret)).To(Succeed())
724+
Expect(agentSecret.Data).NotTo(BeEmpty())
725+
Expect(agentSecret.Data).To(HaveKey("ignition-token"))
726+
Expect(string(agentSecret.Data["ignition-token"])).To(Equal(ignitionToken))
727+
728+
ignitionConfig.Ignition.Config.Merge[0].HTTPHeaders[0].Value = swag.String("Bearer new-token")
729+
updatedIgnitionConfig, err := json.Marshal(ignitionConfig)
730+
Expect(err).To(BeNil())
731+
ignitionTokenSecret.Data["value"] = updatedIgnitionConfig
732+
Expect(c.Update(ctx, ignitionTokenSecret)).To(Succeed())
733+
734+
result, err = amr.Reconcile(ctx, newAgentMachineRequest(agentMachine))
735+
Expect(err).To(BeNil())
736+
Expect(result).To(Equal(ctrl.Result{}))
737+
738+
Expect(c.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("agent-%s", *ignitionTokenSecretName), Namespace: testNamespace}, agentSecret)).To(Succeed())
739+
Expect(agentSecret.Data).NotTo(BeEmpty())
740+
Expect(agentSecret.Data).To(HaveKey("ignition-token"))
741+
Expect(string(agentSecret.Data["ignition-token"])).To(Equal("new-token"))
742+
743+
})
744+
It("creates the ignition token secret even when the AgentMachine is already ready", func() {
745+
agentMachine.Status.AgentRef = &capiproviderv1.AgentReference{Namespace: agent.Namespace, Name: agent.Name}
746+
agentMachine.Status.Ready = true
747+
Expect(c.Update(ctx, agentMachine)).To(Succeed())
748+
749+
ignitionTokenSecretName := machine.Spec.Bootstrap.DataSecretName
750+
agentSecret := &corev1.Secret{}
751+
err := c.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("agent-%s", *ignitionTokenSecretName), Namespace: testNamespace}, agentSecret)
752+
Expect(err).To(HaveOccurred())
753+
Expect(apierrors.IsNotFound(err)).To(BeTrue())
754+
755+
result, err := amr.Reconcile(ctx, newAgentMachineRequest(agentMachine))
756+
Expect(err).To(BeNil())
757+
Expect(result).To(Equal(ctrl.Result{}))
758+
759+
ignitionTokenSecret := &corev1.Secret{}
760+
Expect(c.Get(ctx, types.NamespacedName{Name: *ignitionTokenSecretName, Namespace: testNamespace}, ignitionTokenSecret)).To(Succeed())
761+
ignitionConfig := &ignitionapi.Config{}
762+
Expect(json.Unmarshal(ignitionTokenSecret.Data["value"], ignitionConfig)).To(Succeed())
763+
expectedPrefix := "Bearer "
764+
ignitionToken := (*ignitionConfig.Ignition.Config.Merge[0].HTTPHeaders[0].Value)[len(expectedPrefix):]
765+
766+
Expect(c.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("agent-%s", *ignitionTokenSecretName), Namespace: testNamespace}, agentSecret)).To(Succeed())
767+
Expect(agentSecret.Data).NotTo(BeEmpty())
768+
Expect(agentSecret.Data).To(HaveKey("ignition-token"))
769+
Expect(string(agentSecret.Data["ignition-token"])).To(Equal(ignitionToken))
770+
771+
})
772+
})
670773
})
671774

672775
var _ = Describe("mapMachineToAgentMachine", func() {

0 commit comments

Comments
 (0)