go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/platform/detector/platform_resolver.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package detector 5 6 import ( 7 "github.com/rs/zerolog/log" 8 "go.mondoo.com/cnquery/motor/platform" 9 "go.mondoo.com/cnquery/motor/providers/container/docker_engine" 10 "go.mondoo.com/cnquery/motor/providers/os" 11 "go.mondoo.com/cnquery/motor/providers/tar" 12 ) 13 14 type detect func(r *PlatformResolver, pf *platform.Platform, p os.OperatingSystemProvider) (bool, error) 15 16 type PlatformResolver struct { 17 Name string 18 IsFamily bool 19 Children []*PlatformResolver 20 Detect detect 21 } 22 23 func (r *PlatformResolver) Resolve(p os.OperatingSystemProvider) (*platform.Platform, bool) { 24 // prepare detect info object 25 di := &platform.Platform{} 26 di.Family = make([]string, 0) 27 28 // start recursive platform resolution 29 pi, resolved := r.resolvePlatform(di, p) 30 31 // if we have a container image use the architecture specified in the transport as it is resolved 32 // using the container image properties 33 tarTransport, ok := p.(*tar.Provider) 34 if resolved && ok { 35 pi.Arch = tarTransport.PlatformArchitecture 36 37 // if the platform name is not set, we should fallback to the scratch operating system 38 if len(pi.Name) == 0 { 39 di.Name = "scratch" 40 di.Arch = tarTransport.PlatformArchitecture 41 return di, true 42 } 43 } 44 45 _, ok = p.(*docker_engine.Provider) 46 if resolved && ok { 47 pi.Arch = p.(*docker_engine.Provider).PlatformArchitecture 48 // if the platform name is not set, we should fallback to the scratch operating system 49 if len(pi.Name) == 0 { 50 di.Name = "scratch" 51 di.Arch = pi.Arch 52 return di, true 53 } 54 } 55 56 log.Debug().Str("platform", pi.Name).Strs("family", pi.Family).Msg("platform> detected os") 57 return pi, resolved 58 } 59 60 // Resolve tries to find recursively all 61 // platforms until a leaf (operating systems) detect 62 // mechanism is returning true 63 func (r *PlatformResolver) resolvePlatform(pf *platform.Platform, p os.OperatingSystemProvider) (*platform.Platform, bool) { 64 detected, err := r.Detect(r, pf, p) 65 if err != nil { 66 return pf, false 67 } 68 69 // if detection is true but we have a family 70 if detected == true && r.IsFamily == true { 71 // we are a family and we may have children to try 72 for _, c := range r.Children { 73 detected, resolved := c.resolvePlatform(pf, p) 74 if resolved { 75 // add family hierarchy 76 detected.Family = append(pf.Family, r.Name) 77 return detected, resolved 78 } 79 } 80 81 // we reached this point, we know it is the platform but we could not 82 // identify the system 83 // TODO: add generic platform instance 84 // TODO: should we return an error? 85 } 86 87 // return if the detect is true and we have a leaf 88 if detected && r.IsFamily == false { 89 return pf, true 90 } 91 92 // could not find it 93 return pf, false 94 }