-
Notifications
You must be signed in to change notification settings - Fork 51
util: Add MultiTemplateDir to support multi-segment path in template #682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,6 +59,7 @@ type Template struct { | |
| ConfigOptions map[string]interface{} // map of parameters as input data to render the templates | ||
| SkipSetOwner bool // skip setting ownership on the associated configmap | ||
| Version string // optional version string to separate templates inside the InstanceType/Type directory. E.g. placementapi/config/18.0 | ||
| MultiTemplateDir string // templates dir for multi-group operators, e.g. nova/api; requires InstanceType to be set | ||
| } | ||
|
|
||
| // GetTemplatesPath get path to templates, either running local or deployed as container | ||
|
|
@@ -83,20 +84,21 @@ func GetTemplatesPath() (string, error) { | |
|
|
||
| // GetAllTemplates - get all template files | ||
| // | ||
| // The structur of the folder is, base path, the kind (CRD in lower case), | ||
| // The structure of the folder is, base path, subdir, templateType, version | ||
| // - path - base path of the templates folder | ||
| // - kind - sub folder for the CRDs templates | ||
| // - subdir - directory under that root: one segment (legacy InstanceType, e.g. NovaAPI) or | ||
| // multi-segment (e.g. nova/api from MultiTemplateDir) | ||
| // - templateType - TType of the templates. When the templates got rendered and added to a CM | ||
| // this information is e.g. used for the permissions they get mounted into the pod | ||
| // - version - if there need to be templates for different versions, they can be stored in a version subdir | ||
| // | ||
| // Sub directories inside the specified directory with the above parameters get ignored. | ||
| func GetAllTemplates(path string, kind string, templateType string, version string) []string { | ||
| func GetAllTemplates(path string, subdir string, templateType string, version string) []string { | ||
|
gibizer marked this conversation as resolved.
|
||
|
|
||
| templatePath := filepath.Join(path, strings.ToLower(kind), templateType, "*") | ||
| templatePath := filepath.Join(path, subdir, templateType, "*") | ||
|
|
||
| if version != "" { | ||
| templatePath = filepath.Join(path, strings.ToLower(kind), templateType, version, "*") | ||
| templatePath = filepath.Join(path, subdir, templateType, version, "*") | ||
| } | ||
|
|
||
| templatesFiles, err := filepath.Glob(templatePath) | ||
|
|
@@ -293,8 +295,24 @@ func GetTemplateData(t Template) (map[string]string, error) { | |
| data := make(map[string]string) | ||
|
|
||
| if t.Type != TemplateTypeNone { | ||
| // get all scripts templates which are in ../templesPath/cr.Kind/CMType/<OSPVersion - optional> | ||
| templatesFiles := GetAllTemplates(templatesPath, t.InstanceType, string(t.Type), string(t.Version)) | ||
| // If MultiTemplateDir is set but InstanceType is not, return an error | ||
| // though we do not use InstanceType here, but it is used in secret.go | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I see it in https://github.com/openstack-k8s-operators/lib-common/blame/3e1007da0cbd673047305e423866c8c50b1e3167/modules/common/secret/secret.go#L272 I'm wondering why we are setting an owner label on a Secret this way instead of using the owner reference way. Also it is strange that we only do that on Secret but not on ConfigMap.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, the owner label is coming from creating/tracking object in different namespaces. There is one use case I know of where we create secret in a different namespace and this is for BMH provisioning, where userdata and networkdata secret needs to be created in the bmh namespaces , https://github.com/openstack-k8s-operators/openstack-baremetal-operator/blob/main/internal/openstackbaremetalset/baremetalhost.go#L83 , Just from a quick search it is not using the labels, for delete its using name https://github.com/openstack-k8s-operators/openstack-baremetal-operator/blob/main/internal/openstackbaremetalset/baremetalhost.go#L318, but I think its still good to see from the labels who the owner is, if someone checks the env and wonders who created those secrets in the bmh namespace. Therefore I don't think we should remove it. We can consider supporting it for CMs as well in a follow up. I wanted to spend more time on lib-common to cleanup/align things, but got other prios. Maybe after FR6 I can spend some time on this. |
||
| if t.MultiTemplateDir != "" && t.InstanceType == "" { | ||
| return nil, ErrInstanceTypeUnsetWithMultiTemplateDir | ||
| } | ||
|
|
||
| var templateSubdir string | ||
| // if MultiTemplateDir is set, it will take precedence over InstanceType | ||
| // otherwise, InstanceType is used to create the template subdir based on CRD name | ||
| if t.MultiTemplateDir != "" { | ||
|
gibizer marked this conversation as resolved.
|
||
| templateSubdir = t.MultiTemplateDir | ||
| } else { | ||
| templateSubdir = strings.ToLower(t.InstanceType) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good, we are doing the ToLower here, was wondering above |
||
| } | ||
| if templateSubdir == "" { | ||
| return nil, fmt.Errorf("%w: type is %q", ErrTemplateSubdirUnset, t.Type) | ||
| } | ||
| templatesFiles := GetAllTemplates(templatesPath, templateSubdir, string(t.Type), string(t.Version)) | ||
|
|
||
| // render all template files | ||
| for _, file := range templatesFiles { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -300,14 +300,14 @@ func TestGetAllTemplates(t *testing.T) { | |
|
|
||
| tests := []struct { | ||
| name string | ||
| kind string | ||
| subdir string | ||
| tmplType TType | ||
| version string | ||
| want []string | ||
| }{ | ||
| { | ||
| name: "Get TemplateTypeConfig templates with no version", | ||
| kind: "testservice", | ||
| subdir: "testservice", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we should use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Used |
||
| tmplType: TemplateTypeConfig, | ||
| version: "", | ||
| want: []string{ | ||
|
|
@@ -318,7 +318,7 @@ func TestGetAllTemplates(t *testing.T) { | |
| }, | ||
| { | ||
| name: "Get TemplateTypeScripts templates with version", | ||
| kind: "testservice", | ||
| subdir: "testservice", | ||
| tmplType: TemplateTypeScripts, | ||
| version: "1.0", | ||
| want: []string{ | ||
|
|
@@ -334,7 +334,7 @@ func TestGetAllTemplates(t *testing.T) { | |
| p, _ := GetTemplatesPath() | ||
| g.Expect(p).To(BeADirectory()) | ||
|
|
||
| templatesFiles := GetAllTemplates(p, tt.kind, string(tt.tmplType), tt.version) | ||
| templatesFiles := GetAllTemplates(p, tt.subdir, string(tt.tmplType), tt.version) | ||
|
|
||
| g.Expect(templatesFiles).To(HaveLen(len(tt.want))) | ||
| g.Expect(templatesFiles).Should(HaveEach(BeARegularFile())) | ||
|
|
@@ -366,7 +366,7 @@ func TestGetTemplateData(t *testing.T) { | |
| Name: "testservice", | ||
| Namespace: "somenamespace", | ||
| Type: TemplateTypeConfig, | ||
| InstanceType: "testservice", | ||
| InstanceType: "TestService", | ||
| Version: "", | ||
| ConfigOptions: map[string]interface{}{ | ||
| "ServiceUser": "foo", | ||
|
|
@@ -382,6 +382,75 @@ func TestGetTemplateData(t *testing.T) { | |
| }, | ||
| error: false, | ||
| }, | ||
| { | ||
| name: "Render TemplateTypeConfig using MultiTemplateDir with InstanceType", | ||
| tmpl: Template{ | ||
| Name: "testservice", | ||
| Namespace: "somenamespace", | ||
| Type: TemplateTypeConfig, | ||
| InstanceType: "wrong-unused", | ||
| MultiTemplateDir: "testservice", | ||
|
bogdando marked this conversation as resolved.
|
||
| Version: "", | ||
| ConfigOptions: map[string]interface{}{ | ||
| "ServiceUser": "foo", | ||
| "Count": 1, | ||
| "Upper": "BAR", | ||
| }, | ||
| AdditionalTemplate: map[string]string{}, | ||
| }, | ||
| want: map[string]string{ | ||
| "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", | ||
| "config.json": "{\n \"command\": \"/usr/sbin/httpd -DFOREGROUND\",\n}\n", | ||
| "foo.conf": "username = foo\ncount = 1\nadd = 3\nlower = bar\n", | ||
| }, | ||
| error: false, | ||
| }, | ||
| { | ||
| name: "Render TemplateTypeConfig using MultiTemplateDir test/service with InstanceType", | ||
| tmpl: Template{ | ||
| Name: "testservice", | ||
| Namespace: "somenamespace", | ||
| Type: TemplateTypeConfig, | ||
| InstanceType: "wrong-unused", | ||
| MultiTemplateDir: "test/service", | ||
| Version: "", | ||
| ConfigOptions: map[string]interface{}{ | ||
| "ServiceUser": "foo", | ||
| "Count": 1, | ||
| "Upper": "BAR", | ||
| }, | ||
| AdditionalTemplate: map[string]string{}, | ||
| }, | ||
| want: map[string]string{ | ||
| "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", | ||
| "config.json": "{\n \"command\": \"/usr/sbin/httpd -DFOREGROUND\",\n}\n", | ||
| "foo.conf": "username = foo\ncount = 1\nadd = 3\nlower = bar\n", | ||
| }, | ||
| error: false, | ||
| }, | ||
| { | ||
| name: "TemplateTypeConfig with MultiTemplateDir and empty InstanceType errors", | ||
| tmpl: Template{ | ||
| Name: "testservice", | ||
| Namespace: "somenamespace", | ||
| Type: TemplateTypeConfig, | ||
| MultiTemplateDir: "testservice", | ||
| ConfigOptions: map[string]interface{}{"ServiceUser": "foo"}, | ||
| }, | ||
| want: map[string]string{}, | ||
| error: true, | ||
| }, | ||
| { | ||
| name: "TemplateTypeConfig with empty InstanceType and MultiTemplateDir errors", | ||
| tmpl: Template{ | ||
| Name: "testservice", | ||
| Namespace: "somenamespace", | ||
| Type: TemplateTypeConfig, | ||
| ConfigOptions: map[string]interface{}{"ServiceUser": "foo"}, | ||
| }, | ||
| want: map[string]string{}, | ||
| error: true, | ||
| }, | ||
| { | ||
| name: "Render TemplateTypeScripts templates with version", | ||
| tmpl: Template{ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| {{define "bar-template"}} | ||
| [DEFAULT] | ||
| state_path = /var/lib/nova | ||
|
|
||
|
|
||
| debug=true | ||
|
|
||
| some_parameter_with_brackets=[test] | ||
| compute_driver = libvirt.LibvirtDriver | ||
|
|
||
|
|
||
|
|
||
|
|
||
| [oslo_concurrency] | ||
| lock_path = /var/lib/nova/tmp | ||
| {{end}} | ||
| {{- $var := execTempl "bar-template" . | removeNewLinesInSections -}} | ||
| {{$var -}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "command": "/usr/sbin/httpd -DFOREGROUND", | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| username = {{ .ServiceUser }} | ||
| count = {{ .Count }} | ||
| add = {{ (add 1 2) }} | ||
| lower = {{ (lower .Upper) }} |
Uh oh!
There was an error while loading. Please reload this page.