Skip to content

Commit f90e76d

Browse files
committed
x-pack/filebeat/input/entityanalytics/provider/jamf: wire Jamf into minimal-state registry
Register the entcollect Jamf provider under the "jamf" name so that the entity-analytics input can use it in minimal-state mode (use_minimal_state: true). The registration mirrors the pattern established by the beats shim merged in elastic#49871. A local UCF-tagged struct (localConf) is defined inside minimalProvider to bridge the ucfg config dialect (config:"" tags) to ecjamf.Config, which uses json:"" tags for cross-runtime portability. Fields are mapped explicitly so that a mismatch is a compile error rather than a silent zero. TestMinimalConfigRoundTrip guards against future drift: if ecjamf.Config gains a new field the field-count assertion fails, forcing localConf and the test to be updated together. Assisted-By: Cursor (claude-opus-4-6)
1 parent 036ecc9 commit f90e76d

6 files changed

Lines changed: 130 additions & 5 deletions

File tree

NOTICE.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11452,11 +11452,11 @@ Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-s
1145211452

1145311453
--------------------------------------------------------------------------------
1145411454
Dependency : github.com/elastic/entcollect
11455-
Version: v0.0.0-20260408214411-765a9bedd20c
11455+
Version: v0.0.0-20260501012805-5fd94422b104
1145611456
Licence type (autodetected): Elastic
1145711457
--------------------------------------------------------------------------------
1145811458

11459-
Contents of probable licence file $GOMODCACHE/github.com/elastic/entcollect@v0.0.0-20260408214411-765a9bedd20c/LICENSE.txt:
11459+
Contents of probable licence file $GOMODCACHE/github.com/elastic/entcollect@v0.0.0-20260501012805-5fd94422b104/LICENSE.txt:
1146011460

1146111461
Elastic License 2.0
1146211462

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: feature
2+
summary: Add Jamf provider support for entity analytics minimal-state mode.
3+
component: filebeat

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ require (
236236
github.com/apache/arrow-go/v18 v18.4.1
237237
github.com/cilium/ebpf v0.21.0
238238
github.com/coder/websocket v1.8.14
239-
github.com/elastic/entcollect v0.0.0-20260408214411-765a9bedd20c
239+
github.com/elastic/entcollect v0.0.0-20260501012805-5fd94422b104
240240
github.com/elastic/gokrb5/v8 v8.0.0-20251105095404-23cc45e6a102
241241
github.com/mattn/go-sqlite3 v1.14.32
242242
github.com/parsiya/golnk v0.0.0-20251207220015-443df11fe4fb

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,8 +389,8 @@ github.com/elastic/elastic-agent-system-metrics v0.14.3 h1:v867kcgCVguOX3AYIHEVn
389389
github.com/elastic/elastic-agent-system-metrics v0.14.3/go.mod h1:JNfnZrC0viAjlJRUzQKKuMpDlXgjXBn4WdWEXQF7jcA=
390390
github.com/elastic/elastic-transport-go/v8 v8.8.0 h1:7k1Ua+qluFr6p1jfJjGDl97ssJS/P7cHNInzfxgBQAo=
391391
github.com/elastic/elastic-transport-go/v8 v8.8.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
392-
github.com/elastic/entcollect v0.0.0-20260408214411-765a9bedd20c h1:Mad7EnSJiXwg0HokotucGjGRLyrdHSqFEkVWw75xU2M=
393-
github.com/elastic/entcollect v0.0.0-20260408214411-765a9bedd20c/go.mod h1:jEKK/XEA4Xnu0ssVhLBlExQHPwb1A0b1E2MsPLlpxmY=
392+
github.com/elastic/entcollect v0.0.0-20260501012805-5fd94422b104 h1:en8CqvVRWRToaE++kq+pjJGD7WZJtY8hGRmuc3O8zso=
393+
github.com/elastic/entcollect v0.0.0-20260501012805-5fd94422b104/go.mod h1:jEKK/XEA4Xnu0ssVhLBlExQHPwb1A0b1E2MsPLlpxmY=
394394
github.com/elastic/fsevents v0.0.0-20181029231046-e1d381a4d270 h1:cWPqxlPtir4RoQVCpGSRXmLqjEHpJKbR60rxh1nQZY4=
395395
github.com/elastic/fsevents v0.0.0-20181029231046-e1d381a4d270/go.mod h1:Msl1pdboCbArMF/nSCDUXgQuWTeoMmE/z8607X+k7ng=
396396
github.com/elastic/fsnotify v1.6.1-0.20240920222514-49f82bdbc9e3 h1:UyNbxdkQiSfyipwsOCWAlO+ju3xXC61Z4prx/HBTtFk=
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package jamf
6+
7+
import (
8+
"time"
9+
10+
"github.com/elastic/elastic-agent-libs/config"
11+
"github.com/elastic/elastic-agent-libs/logp"
12+
13+
"github.com/elastic/entcollect"
14+
ecjamf "github.com/elastic/entcollect/provider/jamf"
15+
16+
"github.com/elastic/beats/v7/x-pack/filebeat/input/entityanalytics/provider"
17+
)
18+
19+
func init() {
20+
err := provider.RegisterMinimalStateProvider(Name, minimalProvider)
21+
if err != nil {
22+
panic(err)
23+
}
24+
}
25+
26+
func minimalProvider(cfg *config.C, _ *logp.Logger) (entcollect.Provider, time.Duration, time.Duration, error) {
27+
// localConf mirrors ecjamf.Config with config:"" tags for UCF Unpack.
28+
// If ecjamf.Config gains a new field, add it here and in the mapping
29+
// below; TestMinimalConfigRoundTrip (minimal_test.go) will catch any drift.
30+
type localConf struct {
31+
TenantID string `config:"jamf_tenant" validate:"required"`
32+
Username string `config:"jamf_username" validate:"required"`
33+
Password string `config:"jamf_password" validate:"required"`
34+
PageSize int `config:"page_size"`
35+
IDSetShards int `config:"idset_shards"`
36+
TokenGrace time.Duration `config:"token_grace_period"`
37+
SyncInterval time.Duration `config:"sync_interval"`
38+
UpdateInterval time.Duration `config:"update_interval"`
39+
}
40+
41+
d := ecjamf.DefaultConfig()
42+
lc := localConf{
43+
PageSize: d.PageSize,
44+
IDSetShards: d.IDSetShards,
45+
TokenGrace: d.TokenGrace,
46+
SyncInterval: d.SyncInterval,
47+
UpdateInterval: d.UpdateInterval,
48+
}
49+
if err := cfg.Unpack(&lc); err != nil {
50+
return nil, 0, 0, err
51+
}
52+
ec := ecjamf.Config{
53+
TenantID: lc.TenantID,
54+
Username: lc.Username,
55+
Password: lc.Password,
56+
PageSize: lc.PageSize,
57+
IDSetShards: lc.IDSetShards,
58+
TokenGrace: lc.TokenGrace,
59+
SyncInterval: lc.SyncInterval,
60+
UpdateInterval: lc.UpdateInterval,
61+
}
62+
if err := ec.Validate(); err != nil {
63+
return nil, 0, 0, err
64+
}
65+
return ecjamf.New(ec), ec.SyncInterval, ec.UpdateInterval, nil
66+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package jamf
6+
7+
import (
8+
"reflect"
9+
"testing"
10+
"time"
11+
12+
"github.com/elastic/elastic-agent-libs/config"
13+
ecjamf "github.com/elastic/entcollect/provider/jamf"
14+
)
15+
16+
// TestMinimalConfigRoundTrip verifies that every exported field of
17+
// ecjamf.Config is represented in the localConf mirror inside
18+
// minimalProvider. It does this in two ways:
19+
//
20+
// 1. Field-count assertion — if ecjamf.Config gains a field, the count
21+
// check fails, forcing the developer to update localConf and this test.
22+
// 2. Functional round-trip — all fields are set to non-default sentinel
23+
// values; the returned sync intervals must match, confirming that at
24+
// least the duration fields are wired through end-to-end.
25+
func TestMinimalConfigRoundTrip(t *testing.T) {
26+
const wantFields = 8
27+
if got := reflect.TypeOf(ecjamf.Config{}).NumField(); got != wantFields {
28+
t.Fatalf("ecjamf.Config has %d exported fields, want %d; "+
29+
"update localConf inside minimalProvider and this test", got, wantFields)
30+
}
31+
32+
wantSync := 48 * time.Hour
33+
wantUpdate := 30 * time.Minute
34+
35+
cfg := config.MustNewConfigFrom(map[string]any{
36+
"jamf_tenant": "tenant.jamfcloud.com",
37+
"jamf_username": "user",
38+
"jamf_password": "pass",
39+
"page_size": 50,
40+
"idset_shards": 32,
41+
"token_grace_period": "2m",
42+
"sync_interval": wantSync.String(),
43+
"update_interval": wantUpdate.String(),
44+
})
45+
46+
_, gotSync, gotUpdate, err := minimalProvider(cfg, nil)
47+
if err != nil {
48+
t.Fatalf("minimalProvider returned unexpected error: %v", err)
49+
}
50+
if gotSync != wantSync {
51+
t.Errorf("sync_interval: got %v, want %v", gotSync, wantSync)
52+
}
53+
if gotUpdate != wantUpdate {
54+
t.Errorf("update_interval: got %v, want %v", gotUpdate, wantUpdate)
55+
}
56+
}

0 commit comments

Comments
 (0)