Skip to content

Commit 72bdd58

Browse files
authored
Merge pull request #694 from fmount/templates
Dedup some httpd related templates
2 parents a2ed0e1 + 577ad48 commit 72bdd58

5 files changed

Lines changed: 153 additions & 0 deletions

File tree

modules/common/util/errors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,6 @@ var (
2929
ErrTemplateSubdirUnset = errors.New("template subdir not set")
3030
// ErrInstanceTypeUnsetWithMultiTemplateDir indicates InstanceType is empty while MultiTemplateDir is set
3131
ErrInstanceTypeUnsetWithMultiTemplateDir = errors.New("instance type not set")
32+
// ErrCommonTemplateNotFound indicates a requested common template does not exist
33+
ErrCommonTemplateNotFound = errors.New("common template not found")
3234
)

modules/common/util/template_util.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ package util
1919
import (
2020
"bufio"
2121
"bytes"
22+
"embed"
2223
"fmt"
24+
"io/fs"
2325
"os"
2426
"path"
2527
"path/filepath"
@@ -29,6 +31,9 @@ import (
2931
corev1 "k8s.io/api/core/v1"
3032
)
3133

34+
//go:embed templates/common/config/*
35+
var commonTemplates embed.FS
36+
3237
// TType - TemplateType
3338
type TType string
3439

@@ -60,6 +65,7 @@ type Template struct {
6065
SkipSetOwner bool // skip setting ownership on the associated configmap
6166
Version string // optional version string to separate templates inside the InstanceType/Type directory. E.g. placementapi/config/18.0
6267
MultiTemplateDir string // templates dir for multi-group operators, e.g. nova/api; requires InstanceType to be set
68+
CommonTemplates []string // list of common embedded templates to include (e.g. []string{"ssl.conf"}).
6369
}
6470

6571
// GetTemplatesPath get path to templates, either running local or deployed as container
@@ -293,6 +299,24 @@ func GetTemplateData(t Template) (map[string]string, error) {
293299

294300
data := make(map[string]string)
295301

302+
// Render requested common embedded templates as fallback defaults.
303+
// Note that local operator templates rendered below overwrite the common
304+
// ones: if they share the same filename, service operators definition take
305+
// precedence
306+
if len(t.CommonTemplates) > 0 {
307+
commonData, err := GetCommonTemplates(opts)
308+
if err != nil {
309+
return nil, err
310+
}
311+
for _, name := range t.CommonTemplates {
312+
v, ok := commonData[name]
313+
if !ok {
314+
return nil, fmt.Errorf("%w: %s", ErrCommonTemplateNotFound, name)
315+
}
316+
data[name] = v
317+
}
318+
}
319+
296320
if t.Type != TemplateTypeNone {
297321
// If MultiTemplateDir is set but InstanceType is not, return an error
298322
// though we do not use InstanceType here, but it is used in secret.go
@@ -344,3 +368,34 @@ func GetTemplateData(t Template) (map[string]string, error) {
344368

345369
return data, nil
346370
}
371+
372+
// GetCommonTemplates renders the common config templates (ssl.conf, etc.)
373+
// shipped with lib-common using the provided configOptions, and returns
374+
// map[filename]renderedContent.
375+
// Callers merge the result into their Template.CustomData before calling
376+
// EnsureSecrets/EnsureConfigMaps so that common templates are included in the
377+
// generated Secret/ConfigMaps without each operator duplicating the files.
378+
func GetCommonTemplates(configOptions map[string]any) (map[string]string, error) {
379+
dir := "templates/common/config"
380+
entries, err := fs.ReadDir(commonTemplates, dir)
381+
if err != nil {
382+
return nil, err
383+
}
384+
385+
result := make(map[string]string, len(entries))
386+
for _, e := range entries {
387+
if e.IsDir() {
388+
continue
389+
}
390+
data, err := fs.ReadFile(commonTemplates, path.Join(dir, e.Name()))
391+
if err != nil {
392+
return nil, err
393+
}
394+
rendered, err := ExecuteTemplateData(string(data), configOptions)
395+
if err != nil {
396+
return nil, err
397+
}
398+
result[e.Name()] = rendered
399+
}
400+
return result, nil
401+
}

modules/common/util/template_util_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,66 @@ function common_func {
575575
want: map[string]string{},
576576
error: true,
577577
},
578+
{
579+
name: "CommonTemplates are injected",
580+
tmpl: Template{
581+
Name: "testservice",
582+
Namespace: "somenamespace",
583+
Type: TemplateTypeConfig,
584+
InstanceType: "testservice",
585+
CommonTemplates: []string{"ssl.conf"},
586+
ConfigOptions: map[string]any{
587+
"ServiceUser": "foo",
588+
"Count": 1,
589+
"Upper": "BAR",
590+
},
591+
},
592+
want: map[string]string{
593+
"bar.conf": "[DEFAULT]\nstate_path = /var/lib/nova\ndebug=true\nsome_parameter_with_brackets=[test]\ncompute_driver = libvirt.LibvirtDriver\n\n[oslo_concurrency]\nlock_path = /var/lib/nova/tmp\n",
594+
"config.json": "{\n \"command\": \"/usr/sbin/httpd -DFOREGROUND\",\n}\n",
595+
"foo.conf": "username = foo\ncount = 1\nadd = 3\nlower = bar\n",
596+
"ssl.conf": "", // placeholder, replaced below
597+
},
598+
error: false,
599+
},
600+
{
601+
name: "Unknown CommonTemplate returns error",
602+
tmpl: Template{
603+
Name: "testservice",
604+
Namespace: "somenamespace",
605+
Type: TemplateTypeConfig,
606+
InstanceType: "testservice",
607+
CommonTemplates: []string{"sls.conf"},
608+
},
609+
want: nil,
610+
error: true,
611+
},
612+
{
613+
name: "Local service templates take precedence",
614+
tmpl: Template{
615+
Name: "override",
616+
Namespace: "somenamespace",
617+
Type: TemplateTypeConfig,
618+
InstanceType: "override",
619+
CommonTemplates: []string{"ssl.conf"},
620+
ConfigOptions: map[string]any{},
621+
},
622+
want: map[string]string{
623+
"ssl.conf": "# operator-specific ssl.conf override\nSSLProtocol -all +TLSv1.3\n",
624+
},
625+
error: false,
626+
},
627+
}
628+
629+
// Fill in the expected ssl.conf content for the CommonTemplates test
630+
commonTmpls, err := GetCommonTemplates(map[string]any{})
631+
if err != nil {
632+
panic("Failed to get common templates: " + err.Error())
633+
}
634+
for i, tt := range tests {
635+
if v, ok := tt.want["ssl.conf"]; ok && v == "" {
636+
tests[i].want["ssl.conf"] = commonTmpls["ssl.conf"]
637+
}
578638
}
579639

580640
for _, tt := range tests {
@@ -618,3 +678,16 @@ baz=1
618678

619679
g.Expect(cleaned2).To(Equal(cleaned))
620680
}
681+
682+
func TestGetCommonTemplates(t *testing.T) {
683+
t.Run("Returns ssl.conf", func(t *testing.T) {
684+
g := NewWithT(t)
685+
686+
result, err := GetCommonTemplates(map[string]interface{}{})
687+
g.Expect(err).NotTo(HaveOccurred())
688+
g.Expect(result).To(HaveKey("ssl.conf"))
689+
g.Expect(result["ssl.conf"]).To(ContainSubstring("mod_ssl"))
690+
g.Expect(result["ssl.conf"]).To(ContainSubstring("SSLProtocol"))
691+
g.Expect(result["ssl.conf"]).To(ContainSubstring("SSLCipherSuite"))
692+
})
693+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<IfModule mod_ssl.c>
2+
SSLRandomSeed startup builtin
3+
SSLRandomSeed startup file:/dev/urandom 512
4+
SSLRandomSeed connect builtin
5+
SSLRandomSeed connect file:/dev/urandom 512
6+
7+
AddType application/x-x509-ca-cert .crt
8+
AddType application/x-pkcs7-crl .crl
9+
10+
SSLPassPhraseDialog builtin
11+
SSLSessionCache "shmcb:/var/cache/mod_ssl/scache(512000)"
12+
SSLSessionCacheTimeout 300
13+
Mutex default
14+
SSLCryptoDevice builtin
15+
SSLHonorCipherOrder On
16+
SSLUseStapling Off
17+
SSLStaplingCache "shmcb:/run/httpd/ssl_stapling(32768)"
18+
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!RC4:!3DES
19+
SSLProtocol all -SSLv2 -SSLv3 -TLSv1
20+
SSLOptions StdEnvVars
21+
</IfModule>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# operator-specific ssl.conf override
2+
SSLProtocol -all +TLSv1.3

0 commit comments

Comments
 (0)