github.com/google/cadvisor@v0.49.1/container/docker/docker.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Provides global docker information. 16 package docker 17 18 import ( 19 "fmt" 20 "regexp" 21 "strconv" 22 "time" 23 24 dockertypes "github.com/docker/docker/api/types" 25 "golang.org/x/net/context" 26 27 "github.com/google/cadvisor/container/docker/utils" 28 v1 "github.com/google/cadvisor/info/v1" 29 "github.com/google/cadvisor/machine" 30 ) 31 32 var dockerTimeout = 10 * time.Second 33 34 func defaultContext() context.Context { 35 ctx, _ := context.WithTimeout(context.Background(), dockerTimeout) 36 return ctx 37 } 38 39 func SetTimeout(timeout time.Duration) { 40 dockerTimeout = timeout 41 } 42 43 func Status() (v1.DockerStatus, error) { 44 return StatusWithContext(defaultContext()) 45 } 46 47 func StatusWithContext(ctx context.Context) (v1.DockerStatus, error) { 48 client, err := Client() 49 if err != nil { 50 return v1.DockerStatus{}, fmt.Errorf("unable to communicate with docker daemon: %v", err) 51 } 52 dockerInfo, err := client.Info(ctx) 53 if err != nil { 54 return v1.DockerStatus{}, err 55 } 56 return StatusFromDockerInfo(dockerInfo) 57 } 58 59 func StatusFromDockerInfo(dockerInfo dockertypes.Info) (v1.DockerStatus, error) { 60 out := v1.DockerStatus{} 61 out.KernelVersion = machine.KernelVersion() 62 out.OS = dockerInfo.OperatingSystem 63 out.Hostname = dockerInfo.Name 64 out.RootDir = dockerInfo.DockerRootDir 65 out.Driver = dockerInfo.Driver 66 out.NumImages = dockerInfo.Images 67 out.NumContainers = dockerInfo.Containers 68 out.DriverStatus = make(map[string]string, len(dockerInfo.DriverStatus)) 69 for _, v := range dockerInfo.DriverStatus { 70 out.DriverStatus[v[0]] = v[1] 71 } 72 var err error 73 ver, err := VersionString() 74 if err != nil { 75 return out, err 76 } 77 out.Version = ver 78 ver, err = APIVersionString() 79 if err != nil { 80 return out, err 81 } 82 out.APIVersion = ver 83 return out, nil 84 } 85 86 func Images() ([]v1.DockerImage, error) { 87 client, err := Client() 88 if err != nil { 89 return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) 90 } 91 summaries, err := client.ImageList(defaultContext(), dockertypes.ImageListOptions{All: false}) 92 if err != nil { 93 return nil, err 94 } 95 return utils.SummariesToImages(summaries) 96 } 97 98 // Checks whether the dockerInfo reflects a valid docker setup, and returns it if it does, or an 99 // error otherwise. 100 func ValidateInfo(GetInfo func() (*dockertypes.Info, error), ServerVersion func() (string, error)) (*dockertypes.Info, error) { 101 info, err := GetInfo() 102 if err != nil { 103 return nil, err 104 } 105 106 // Fall back to version API if ServerVersion is not set in info. 107 if info.ServerVersion == "" { 108 var err error 109 info.ServerVersion, err = ServerVersion() 110 if err != nil { 111 return nil, fmt.Errorf("unable to get runtime version: %v", err) 112 } 113 } 114 115 version, err := ParseVersion(info.ServerVersion, VersionRe, 3) 116 if err != nil { 117 return nil, err 118 } 119 120 if version[0] < 1 { 121 return nil, fmt.Errorf("cAdvisor requires runtime version %v or above but we have found version %v reported as %q", []int{1, 0, 0}, version, info.ServerVersion) 122 } 123 124 if info.Driver == "" { 125 return nil, fmt.Errorf("failed to find runtime storage driver") 126 } 127 128 return info, nil 129 } 130 131 func Info() (*dockertypes.Info, error) { 132 client, err := Client() 133 if err != nil { 134 return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) 135 } 136 137 dockerInfo, err := client.Info(defaultContext()) 138 if err != nil { 139 return nil, fmt.Errorf("failed to detect Docker info: %v", err) 140 } 141 142 return &dockerInfo, nil 143 } 144 145 func APIVersion() ([]int, error) { 146 ver, err := APIVersionString() 147 if err != nil { 148 return nil, err 149 } 150 return ParseVersion(ver, apiVersionRe, 2) 151 } 152 153 func VersionString() (string, error) { 154 dockerVersion := "Unknown" 155 client, err := Client() 156 if err == nil { 157 version, err := client.ServerVersion(defaultContext()) 158 if err == nil { 159 dockerVersion = version.Version 160 } 161 } 162 return dockerVersion, err 163 } 164 165 func APIVersionString() (string, error) { 166 apiVersion := "Unknown" 167 client, err := Client() 168 if err == nil { 169 version, err := client.ServerVersion(defaultContext()) 170 if err == nil { 171 apiVersion = version.APIVersion 172 } 173 } 174 return apiVersion, err 175 } 176 177 func ParseVersion(versionString string, regex *regexp.Regexp, length int) ([]int, error) { 178 matches := regex.FindAllStringSubmatch(versionString, -1) 179 if len(matches) != 1 { 180 return nil, fmt.Errorf("version string \"%v\" doesn't match expected regular expression: \"%v\"", versionString, regex.String()) 181 } 182 versionStringArray := matches[0][1:] 183 versionArray := make([]int, length) 184 for index, versionStr := range versionStringArray { 185 version, err := strconv.Atoi(versionStr) 186 if err != nil { 187 return nil, fmt.Errorf("error while parsing \"%v\" in \"%v\"", versionStr, versionString) 188 } 189 versionArray[index] = version 190 } 191 return versionArray, nil 192 }