Skip to content

Commit 007dacf

Browse files
committed
Fix pool update job
The pool update job was not launched because it had the same name. As Kubernetes requires names be unique across all API versions of the same resource, the jobs were only triggered once. This patch adds the jobs a unix timestamp suffix to overcome that problem. It also sorts the pool resources to create a comparable hash between jobs.
1 parent a31385d commit 007dacf

File tree

4 files changed

+99
-53
lines changed

4 files changed

+99
-53
lines changed

controllers/designate_controller.go

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,6 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
833833
}
834834

835835
Log.Info("Bind configmap was created successfully")
836-
837836
if len(nsRecordsConfigMap.Data) > 0 && instance.Status.DesignateCentralReadyCount > 0 {
838837
Log.Info("len(nsRecordsConfigMap.Data) > 0")
839838
poolsYamlConfigMap := &corev1.ConfigMap{
@@ -844,11 +843,12 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
844843
},
845844
Data: make(map[string]string),
846845
}
847-
Log.Info("before designate.GeneratePoolsYamlData")
848-
poolsYaml, err := designate.GeneratePoolsYamlData(bindConfigMap.Data, mdnsConfigMap.Data, nsRecordsConfigMap.Data)
846+
847+
poolsYaml, poolsYamlHash, err := designate.GeneratePoolsYamlDataAndHash(bindConfigMap.Data, mdnsConfigMap.Data, nsRecordsConfigMap.Data)
849848
if err != nil {
850849
return ctrl.Result{}, err
851850
}
851+
852852
Log.Info(fmt.Sprintf("pools.yaml content is\n%v", poolsYaml))
853853
updatedPoolsYaml := make(map[string]string)
854854
updatedPoolsYaml[designate.PoolsYamlContent] = poolsYaml
@@ -862,40 +862,32 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
862862
Log.Info("Unable to create config map for pools.yaml file")
863863
return ctrl.Result{}, err
864864
}
865-
configMaps := []interface{}{
866-
poolsYamlConfigMap.Data,
867-
}
868865

869-
poolsYamlsEnvVars := make(map[string]env.Setter)
870-
_, changed, err := r.createHashOfInputHashes(ctx, instance, designate.PoolsYamlHash, poolsYamlsEnvVars, configMaps)
871-
if err != nil {
872-
return ctrl.Result{}, err
866+
if instance.Status.Hash == nil {
867+
instance.Status.Hash = make(map[string]string)
873868
}
874-
if changed {
875-
Log.Info("PoolsYamlHash has changed, creating a pool update job")
876-
877-
var poolUpdateHash string
878-
var ok bool
879-
if poolUpdateHash, ok = instance.Status.Hash[designatev1beta1.PoolUpdateHash]; !ok {
880-
instance.Status.Hash[designatev1beta1.PoolUpdateHash] = ""
881-
poolUpdateHash = ""
869+
870+
oldHash := instance.Status.Hash[designatev1beta1.PoolUpdateHash]
871+
if oldHash != poolsYamlHash {
872+
Log.Info(fmt.Sprintf("Old poolsYamlHash %s is different than new poolsYamlHash %s.\nLaunching pool update job", oldHash, poolsYamlHash))
873+
874+
instance.Status.Hash[designatev1beta1.PoolUpdateHash] = poolsYamlHash
875+
if err := r.Client.Status().Update(ctx, instance); err != nil {
876+
return ctrl.Result{}, fmt.Errorf("failed to update status hash: %w", err)
882877
}
883878
jobDef := designate.PoolUpdateJob(instance, serviceLabels, serviceAnnotations)
884879

885880
Log.Info("Initializing pool update job")
881+
886882
poolUpdatejob := job.NewJob(
887883
jobDef,
888884
designatev1beta1.PoolUpdateHash,
889885
instance.Spec.PreserveJobs,
890886
time.Duration(15)*time.Second,
891-
poolUpdateHash,
887+
oldHash,
892888
)
893-
_, err = poolUpdatejob.DoJob(ctx, helper)
894-
if err != nil {
895-
return ctrl.Result{}, err
896-
}
897-
instance.Status.Hash[designatev1beta1.PoolUpdateHash] = poolUpdatejob.GetHash()
898-
err = r.Client.Status().Update(ctx, instance)
889+
890+
_, err := poolUpdatejob.DoJob(ctx, helper)
899891
if err != nil {
900892
return ctrl.Result{}, err
901893
}

pkg/designate/generate_bind9_pools_yaml.go

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ package designate
1515

1616
import (
1717
"bytes"
18+
"crypto/sha256"
19+
"encoding/hex"
1820
"fmt"
1921
"os"
2022
"path"
23+
"sort"
2124
"text/template"
2225

2326
"gopkg.in/yaml.v2"
@@ -70,49 +73,73 @@ type CatalogZone struct {
7073
Refresh int `yaml:"refresh"`
7174
}
7275

73-
func GeneratePoolsYamlData(BindMap, MdnsMap, NsRecordsMap map[string]string) (string, error) {
74-
// Create ns_records
76+
// We sort all pool resources to get the correct hash every time
77+
func GeneratePoolsYamlDataAndHash(BindMap, MdnsMap, NsRecordsMap map[string]string) (string, string, error) {
7578
nsRecords := []NSRecord{}
7679
for _, data := range NsRecordsMap {
7780
err := yaml.Unmarshal([]byte(data), &nsRecords)
7881
if err != nil {
79-
return "", fmt.Errorf("error unmarshalling yaml: %w", err)
82+
return "", "", fmt.Errorf("error unmarshalling yaml: %w", err)
8083
}
8184
}
85+
sort.Slice(nsRecords, func(i, j int) bool {
86+
if nsRecords[i].Hostname != nsRecords[j].Hostname {
87+
return nsRecords[i].Hostname < nsRecords[j].Hostname
88+
}
89+
return nsRecords[i].Priority < nsRecords[j].Priority
90+
})
91+
92+
bindIPs := make([]string, 0, len(BindMap))
93+
for _, ip := range BindMap {
94+
bindIPs = append(bindIPs, ip)
95+
}
96+
sort.Strings(bindIPs)
8297

83-
// Create targets and nameservers
84-
nameservers := []Nameserver{}
85-
targets := []Target{}
86-
rndcKeyNum := 0
98+
masterHosts := make([]string, 0, len(MdnsMap))
99+
for _, host := range MdnsMap {
100+
masterHosts = append(masterHosts, host)
101+
}
102+
sort.Strings(masterHosts)
87103

88-
for _, bindIP := range BindMap {
89-
nameservers = append(nameservers, Nameserver{
104+
nameservers := make([]Nameserver, len(bindIPs))
105+
for i, bindIP := range bindIPs {
106+
nameservers[i] = Nameserver{
90107
Host: bindIP,
91108
Port: 53,
92-
})
109+
}
110+
}
93111

94-
masters := []Master{}
95-
for _, masterHost := range MdnsMap {
96-
masters = append(masters, Master{
112+
targets := make([]Target, len(bindIPs))
113+
for i, bindIP := range bindIPs {
114+
masters := make([]Master, len(masterHosts))
115+
for j, masterHost := range masterHosts {
116+
masters[j] = Master{
97117
Host: masterHost,
98118
Port: 5354,
99-
})
119+
}
100120
}
101121

102-
target := Target{
122+
targets[i] = Target{
103123
Type: "bind9",
104-
Description: fmt.Sprintf("BIND9 Server %d (%s)", rndcKeyNum, bindIP),
124+
Description: fmt.Sprintf("BIND9 Server %d (%s)", i, bindIP),
105125
Masters: masters,
106126
Options: Options{
107127
Host: bindIP,
108128
Port: 53,
109129
RNDCHost: bindIP,
110130
RNDCPort: 953,
111-
RNDCKeyFile: fmt.Sprintf("%s/%s-%d", RndcConfDir, DesignateRndcKey, rndcKeyNum),
131+
RNDCKeyFile: fmt.Sprintf("%s/%s-%d", RndcConfDir, DesignateRndcKey, i),
112132
},
113133
}
114-
targets = append(targets, target)
115-
rndcKeyNum++
134+
}
135+
136+
sort.Slice(targets, func(i, j int) bool {
137+
return targets[i].Options.Host < targets[j].Options.Host
138+
})
139+
140+
for i := range targets {
141+
targets[i].Description = fmt.Sprintf("BIND9 Server %d (%s)", i, targets[i].Options.Host)
142+
targets[i].Options.RNDCKeyFile = fmt.Sprintf("%s/%s-%d", RndcConfDir, DesignateRndcKey, i)
116143
}
117144

118145
// Catalog zone is an optional section
@@ -132,25 +159,32 @@ func GeneratePoolsYamlData(BindMap, MdnsMap, NsRecordsMap map[string]string) (st
132159
CatalogZone: nil, // set to catalogZone if this section should be presented
133160
}
134161

162+
poolBytes, err := yaml.Marshal(pool)
163+
if err != nil {
164+
return "", "", fmt.Errorf("error marshalling pool for hash: %w", err)
165+
}
166+
hasher := sha256.New()
167+
hasher.Write(poolBytes)
168+
poolHash := hex.EncodeToString(hasher.Sum(nil))
169+
135170
opTemplates, err := util.GetTemplatesPath()
136171
if err != nil {
137-
return "", err
172+
return "", "", err
138173
}
139174
poolsYamlPath := path.Join(opTemplates, PoolsYamlPath)
140175
poolsYaml, err := os.ReadFile(poolsYamlPath)
141176
if err != nil {
142-
return "", err
177+
return "", "", err
143178
}
144179
tmpl, err := template.New("pool").Parse(string(poolsYaml))
145180
if err != nil {
146-
return "", err
181+
return "", "", err
147182
}
148-
149183
var buf bytes.Buffer
150184
err = tmpl.Execute(&buf, pool)
151185
if err != nil {
152-
return "", err
186+
return "", "", err
153187
}
154188

155-
return buf.String(), nil
189+
return buf.String(), poolHash, nil
156190
}

pkg/designate/pool_update.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
batchv1 "k8s.io/api/batch/v1"
88
corev1 "k8s.io/api/core/v1"
99
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"time"
1011
)
1112

1213
const (
@@ -85,9 +86,10 @@ func PoolUpdateJob(
8586
},
8687
)
8788

89+
jobName := fmt.Sprintf("%s-pool-update-%d", ServiceName, time.Now().Unix())
8890
job := &batchv1.Job{
8991
ObjectMeta: metav1.ObjectMeta{
90-
Name: ServiceName + "-pool-update",
92+
Name: jobName,
9193
Namespace: instance.Namespace,
9294
Labels: labels,
9395
},
@@ -101,7 +103,7 @@ func PoolUpdateJob(
101103
ServiceAccountName: instance.RbacResourceName(),
102104
Containers: []corev1.Container{
103105
{
104-
Name: ServiceName + "-pool-update",
106+
Name: jobName,
105107
Image: instance.Spec.DesignateCentral.ContainerImage,
106108
Env: []corev1.EnvVar{
107109
{

tests/functional/designate_controller_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,6 @@ var _ = Describe("Designate controller", func() {
644644
Expect(err).ToNot(HaveOccurred())
645645

646646
validate := validator.New()
647-
648647
for _, pool := range pools {
649648
Expect(pool.Name).ToNot(BeEmpty(), "Pool name should not be an empty string")
650649
Expect(pool.Description).ToNot(BeEmpty(), "Pool description should not be an empty string")
@@ -726,5 +725,24 @@ var _ = Describe("Designate controller", func() {
726725
}
727726
}
728727
})
728+
729+
It("should create the same pools.yaml hash when provided the same designate configmaps", func() {
730+
bindConfigMap := th.GetConfigMap(types.NamespacedName{
731+
Name: designate.BindPredIPConfigMap,
732+
Namespace: namespace})
733+
mdnsConfigMap := th.GetConfigMap(types.NamespacedName{
734+
Name: designate.MdnsPredIPConfigMap,
735+
Namespace: namespace})
736+
nsRecordsConfigMap := th.GetConfigMap(types.NamespacedName{
737+
Name: designate.NsRecordsConfigMap,
738+
Namespace: namespace})
739+
_, poolsYamlHash, err := designate.GeneratePoolsYamlDataAndHash(bindConfigMap.Data, mdnsConfigMap.Data, nsRecordsConfigMap.Data)
740+
Expect(err).ToNot(HaveOccurred())
741+
for i := 0; i < 10; i++ {
742+
_, newPoolsYamlHash, err := designate.GeneratePoolsYamlDataAndHash(bindConfigMap.Data, mdnsConfigMap.Data, nsRecordsConfigMap.Data)
743+
Expect(err).ToNot(HaveOccurred())
744+
Expect(poolsYamlHash).Should(Equal(newPoolsYamlHash))
745+
}
746+
})
729747
})
730748
})

0 commit comments

Comments
 (0)