Skip to content

Commit 5bea3f5

Browse files
committed
Template selection by a subset of tags
(fixes issue #583).
1 parent fc79f9d commit 5bea3f5

File tree

3 files changed

+28
-7
lines changed

3 files changed

+28
-7
lines changed

docs/advanced-setups.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,11 @@ For example, setting it to `0` (zero), entirely disables scheduling based on mem
178178

179179
## Template lookup based on Proxmox tags
180180

181-
Our provider is able to look up templates based on their attached tags, for `ProxmoxMachine` resources, that make use of an tag selector.
181+
Our provider is able to look up templates based on their attached tags, for `ProxmoxMachine` resources, that make use of a tag selector.
182182

183183
For example, you can set the `TEMPLATE_TAGS="tag1,tag2"` environment variable. Your custom image will then be used when using the [auto-image](https://github.com/ionos-cloud/cluster-api-provider-ionoscloud/blob/main/templates/cluster-template-auto-image.yaml) template.
184184

185-
Please note: Passed tags must be an exact 1:1 match with the tags on the template you want to use. The matched result must be unique. If multiple templates are found, provisioning will fail.
185+
Please note: Passed tags will match at least a subset of the tags on the template you want to use. The lookup must result in a unique template. If multiple templates are found, provisioning will fail.
186186

187187
## Proxmox RBAC with least privileges
188188

pkg/proxmox/goproxmox/api_client.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,30 @@ func (c *APIClient) FindVMTemplateByTags(ctx context.Context, templateTags []str
173173
}
174174

175175
vmTags := strings.Split(vm.Tags, ";")
176+
for i := range vmTags {
177+
vmTags[i] = strings.ToLower(strings.TrimSpace(vmTags[i]))
178+
}
176179
slices.Sort(vmTags)
180+
vmTags = slices.Compact(vmTags)
181+
182+
// Check whether the template’s tags (tagsPresent) contain all the requested tags (tagsWanted)
183+
isSuperset := func(tagsPresent, tagsWanted []string) bool {
184+
presentIdx, wantedIdx := 0, 0
185+
for presentIdx < len(tagsPresent) && wantedIdx < len(tagsWanted) {
186+
switch {
187+
case tagsPresent[presentIdx] == tagsWanted[wantedIdx]:
188+
presentIdx++
189+
wantedIdx++
190+
case tagsPresent[presentIdx] < tagsWanted[wantedIdx]:
191+
presentIdx++
192+
default:
193+
return false
194+
}
195+
}
196+
return wantedIdx == len(tagsWanted)
197+
}
177198

178-
if slices.Equal(vmTags, uniqueTags) {
199+
if isSuperset(vmTags, uniqueTags) {
179200
vmTemplates = append(vmTemplates, vm)
180201
}
181202
}

pkg/proxmox/goproxmox/api_client_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ func TestProxmoxAPIClient_FindVMTemplateByTags(t *testing.T) {
416416
http: []int{200, 200},
417417
vmTags: nil,
418418
fails: true,
419-
err: "VM template not found: found 0 VM templates with tags \"\"",
419+
err: "VM template not found: found 4 VM templates with tags \"\"",
420420
vmTemplateNode: "capmox01",
421421
vmTemplateID: 201,
422422
},
@@ -449,16 +449,16 @@ func TestProxmoxAPIClient_FindVMTemplateByTags(t *testing.T) {
449449
vmTemplateID: 202,
450450
},
451451
{
452-
name: "find-multiple-templates",
452+
name: "find-multiple-templates-any-version",
453453
http: []int{200, 200},
454454
vmTags: []string{"template", "capmox"},
455455
fails: true,
456-
err: "VM template not found: found 0 VM templates with tags \"template;capmox\"",
456+
err: "VM template not found: found 4 VM templates with tags \"template;capmox\"",
457457
vmTemplateID: 69,
458458
vmTemplateNode: "nice",
459459
},
460460
{
461-
name: "find-multiple-templates",
461+
name: "find-multiple-templates-v1.29.2",
462462
http: []int{200, 200},
463463
vmTags: []string{"template", "capmox", "v1.29.2"},
464464
fails: true,

0 commit comments

Comments
 (0)