Use host IDs instead of host names when doing generate-gitops for manual labels (#34254)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #34225

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [X] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)

## Testing

- [X] Added/updated automated tests
- [X] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [X] QA'd all new/changed functionality manually
Did a `generate-gitops` for a manual label, noted the correct IDs were
output for hosts. Use `gitops` to re-apply the label, saw the label
membership was applied correctly.

For unreleased bug fixes in a release candidate, one of:

- [X] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed
This commit is contained in:
Scott Gress
2025-10-15 13:31:40 -05:00
committed by GitHub
parent ca61532d66
commit 45a8749d1a
7 changed files with 20 additions and 23 deletions
@@ -401,7 +401,7 @@ func (MockClient) GetLabels() ([]*fleet.LabelSpec, error) {
Name: "Label B",
Description: "Label B description",
LabelMembershipType: fleet.LabelMembershipTypeManual,
Hosts: []string{"host1", "host2"},
Hosts: []string{"1", "2"},
}, {
Name: "Label C",
Description: "Label C description",
@@ -7,8 +7,8 @@
description: Label B description
label_membership_type: manual
hosts:
- host1
- host2
- "1"
- "2"
- name: Label C
description: Label C description
label_membership_type: host_vitals
@@ -38,8 +38,8 @@ labels:
query: SELECT * FROM osquery_info
- description: Label B description
hosts:
- host1
- host2
- "1"
- "2"
label_membership_type: manual
name: Label B
- criteria:
@@ -20,8 +20,8 @@ labels:
query: SELECT * FROM osquery_info
- description: Label B description
hosts:
- host1
- host2
- "1"
- "2"
label_membership_type: manual
name: Label B
- criteria:
+4 -4
View File
@@ -327,7 +327,7 @@ func (ds *Datastore) GetLabelSpecs(ctx context.Context) ([]*fleet.LabelSpec, err
for _, spec := range specs {
if spec.LabelType != fleet.LabelTypeBuiltIn &&
spec.LabelMembershipType == fleet.LabelMembershipTypeManual {
if err := ds.getLabelHostnames(ctx, spec); err != nil {
if err := ds.getLabelHostIDs(ctx, spec); err != nil {
return nil, err
}
}
@@ -356,7 +356,7 @@ WHERE name = ?
spec := specs[0]
if spec.LabelType != fleet.LabelTypeBuiltIn &&
spec.LabelMembershipType == fleet.LabelMembershipTypeManual {
err := ds.getLabelHostnames(ctx, spec)
err := ds.getLabelHostIDs(ctx, spec)
if err != nil {
return nil, err
}
@@ -365,9 +365,9 @@ WHERE name = ?
return spec, nil
}
func (ds *Datastore) getLabelHostnames(ctx context.Context, label *fleet.LabelSpec) error {
func (ds *Datastore) getLabelHostIDs(ctx context.Context, label *fleet.LabelSpec) error {
sql := `
SELECT hostname
SELECT id
FROM hosts
WHERE id IN
(
+8 -11
View File
@@ -752,8 +752,8 @@ func setupLabelSpecsTest(t *testing.T, ds fleet.Datastore) []*fleet.LabelSpec {
SeenTime: time.Now(),
OsqueryHostID: ptr.String(strconv.Itoa(i)),
NodeKey: ptr.String(strconv.Itoa(i)),
UUID: strconv.Itoa(i),
Hostname: strconv.Itoa(i),
UUID: fmt.Sprintf("uuid%s", strconv.Itoa(i)),
Hostname: fmt.Sprintf("host%s", strconv.Itoa(i)),
})
require.Nil(t, err)
}
@@ -790,10 +790,7 @@ func setupLabelSpecsTest(t *testing.T, ds fleet.Datastore) []*fleet.LabelSpec {
err := ds.ApplyLabelSpecs(context.Background(), expectedSpecs)
require.Nil(t, err)
// Because `Hosts` for manual labels matches both host name AND host ID,
// specifying "1" will match both host with ID 1 (whose name is "0")
// and host with name "1".
expectedSpecs[4].Hosts = []string{"0", "1", "2", "3", "4"}
expectedSpecs[4].Hosts = []string{"1", "2", "3", "4"}
return expectedSpecs
}
@@ -1870,8 +1867,8 @@ func testUpdateLabelMembershipByHostIDs(t *testing.T, ds *Datastore) {
require.NoError(t, err)
// label.Hosts contains hostnames
require.Len(t, labelSpec.Hosts, 2)
require.Equal(t, host1.Hostname, labelSpec.Hosts[0])
require.Equal(t, host2.Hostname, labelSpec.Hosts[1])
require.Equal(t, strconv.Itoa(int(host1.ID)), labelSpec.Hosts[0]) //nolint:gosec // dismiss G115
require.Equal(t, strconv.Itoa(int(host2.ID)), labelSpec.Hosts[1]) //nolint:gosec // dismiss G115
labels, err := ds.ListLabelsForHost(ctx, host1.ID)
require.NoError(t, err)
@@ -1977,9 +1974,9 @@ func testUpdateLabelMembershipByHostIDs(t *testing.T, ds *Datastore) {
// label.Hosts contains hostnames
require.Len(t, labelSpec.Hosts, 3)
require.Equal(t, host1.Hostname, labelSpec.Hosts[0])
require.Equal(t, host2.Hostname, labelSpec.Hosts[1])
require.Equal(t, host3.Hostname, labelSpec.Hosts[2])
require.Equal(t, strconv.Itoa(int(host1.ID)), labelSpec.Hosts[0]) //nolint:gosec // dismiss G115
require.Equal(t, strconv.Itoa(int(host2.ID)), labelSpec.Hosts[1]) //nolint:gosec // dismiss G115
require.Equal(t, strconv.Itoa(int(host3.ID)), labelSpec.Hosts[2]) //nolint:gosec // dismiss G115
}
func testApplyLabelSpecsForSerialUUID(t *testing.T, ds *Datastore) {
+1 -1
View File
@@ -214,7 +214,7 @@ func (s *HostsSlice) UnmarshalJSON(data []byte) error {
}
type LabelSpec struct {
ID uint `json:"id"`
ID uint `json:"id" db:"id"`
Name string `json:"name"`
Description string `json:"description"`
Query string `json:"query"`