@@ -3,12 +3,16 @@ package job
3
3
import (
4
4
"context"
5
5
"errors"
6
+ "fmt"
6
7
"os"
8
+ "strings"
9
+ "time"
7
10
8
11
"github.com/fleetdm/fleet/v4/server/android"
9
12
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
10
13
"github.com/fleetdm/fleet/v4/server/fleet"
11
14
kitlog "github.com/go-kit/log"
15
+ "github.com/go-kit/log/level"
12
16
"google.golang.org/api/androidmanagement/v1"
13
17
"google.golang.org/api/option"
14
18
)
@@ -36,16 +40,80 @@ func ReconcileDevices(ctx context.Context, ds fleet.Datastore, androidDS android
36
40
37
41
for _ , enterprise := range enterprises {
38
42
// Note: we can optimize this by using Fields to retrieve partial data https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
43
+ // But actually this is not scalable for 100,000s devices, so we need to use PubSub.
39
44
devices , err := mgmt .Enterprises .Devices .List (enterprise .Name ()).Do ()
40
45
if err != nil {
41
46
return ctxerr .Wrap (ctx , err , "listing devices with Google API" )
42
47
}
43
48
44
49
for _ , device := range devices .Devices {
45
- logger .Log ("msg" , "device" , "device" , device )
50
+ // Get the deviceId from the name: enterprises/{enterpriseId}/devices/{deviceId}
51
+ nameParts := strings .Split (device .Name , "/" )
52
+ if len (nameParts ) != 4 {
53
+ return ctxerr .Errorf (ctx , "invalid Android device name: %s" , device .Name )
54
+ }
55
+ deviceID := nameParts [3 ]
56
+
57
+ host , err := androidDS .GetHost (ctx , enterprise .ID , deviceID )
58
+ if err != nil {
59
+ return ctxerr .Wrap (ctx , err , "getting host" )
60
+ }
61
+ if host != nil {
62
+ // TODO: Update host if needed
63
+ continue
64
+ }
65
+
66
+ // TODO: Do EnrollHost and androidDS.AddHost inside a transaction so we don't add duplicate hosts
67
+ fleetHost , err := ds .EnrollHost (ctx , true , device .HardwareInfo .SerialNumber , device .HardwareInfo .SerialNumber ,
68
+ device .HardwareInfo .SerialNumber , "" , nil , 0 )
69
+ if err != nil {
70
+ return ctxerr .Wrap (ctx , err , "enrolling host" )
71
+ }
72
+ err = androidDS .AddHost (ctx , & android.Host {
73
+ FleetEnterpriseID : enterprise .ID ,
74
+ DeviceID : deviceID ,
75
+ HostID : fleetHost .ID ,
76
+ })
77
+ if err != nil {
78
+ return ctxerr .Wrap (ctx , err , "adding Android host" )
79
+ }
80
+
81
+ fleetHost .DiskEncryptionEnabled = & device .DeviceSettings .IsEncrypted
82
+ fleetHost .Platform = "ubuntu"
83
+ fleetHost .HardwareVendor = device .HardwareInfo .Manufacturer
84
+ fleetHost .HardwareModel = device .HardwareInfo .Model
85
+ fleetHost .OSVersion = "Android " + device .SoftwareInfo .AndroidVersion
86
+ lastEnrolledAt , err := time .Parse (time .RFC3339 , device .EnrollmentTime )
87
+ switch {
88
+ case err != nil :
89
+ level .Error (logger ).Log ("msg" , "parsing Android device last enrolled at" , "err" , err , "deviceId" , deviceID )
90
+ default :
91
+ fleetHost .LastEnrolledAt = lastEnrolledAt
92
+ }
93
+ detailUpdatedAt , err := time .Parse (time .RFC3339 , device .LastStatusReportTime )
94
+ switch {
95
+ case err != nil :
96
+ level .Error (logger ).Log ("msg" , "parsing Android device detail updated at" , "err" , err , "deviceId" , deviceID )
97
+ default :
98
+ fleetHost .DetailUpdatedAt = detailUpdatedAt
99
+ }
100
+ err = ds .UpdateHost (ctx , fleetHost )
101
+ if err != nil {
102
+ return ctxerr .Wrap (ctx , err , fmt .Sprintf ("updating host with deviceId %s" , deviceID ))
103
+ }
104
+
105
+ err = ds .UpdateHostOperatingSystem (ctx , fleetHost .ID , fleet.OperatingSystem {
106
+ Name : "Android" ,
107
+ Version : device .SoftwareInfo .AndroidVersion ,
108
+ Platform : "android" ,
109
+ KernelVersion : device .SoftwareInfo .DeviceKernelVersion ,
110
+ })
111
+ if err != nil {
112
+ return ctxerr .Wrap (ctx , err , fmt .Sprintf ("updating host operating system with deviceId %s" , deviceID ))
113
+ }
114
+
46
115
}
47
116
48
- // For each device, check whether it is in Fleet. If not, add it
49
117
}
50
118
51
119
return nil
0 commit comments