-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathversion.go
More file actions
106 lines (93 loc) · 2.83 KB
/
version.go
File metadata and controls
106 lines (93 loc) · 2.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package dockergo
import (
"encoding/json"
"fmt"
"time"
)
// CheckVersion fetches the local Docker Engine version using the daemon API,
// then compares it against the latest Docker release from GitHub.
// Returns a VersionInfo struct showing both versions and whether they match.
func (c *Client) CheckVersion() (*VersionInfo, error) {
// Step 1: Get local version from Docker daemon
var local dockerVersionResponse
if err := c.httpGetJSON("/version", &local); err != nil {
return nil, fmt.Errorf("failed to get local docker version: %w", err)
}
rawLocal := local.Version
localNormalized := normalizeVersion(rawLocal)
// Step 2: Fetch latest release from Docker’s GitHub repo
latest, err := fetchLatestFromGitHub()
if err != nil {
// Return partial data even if GitHub fetch fails
return &VersionInfo{
Local: localNormalized,
Latest: "",
UpToDate: true,
RawLocal: rawLocal,
}, fmt.Errorf("failed to fetch latest docker release: %w", err)
}
latestNormalized := normalizeVersion(latest)
up := compareVersionsLoose(localNormalized, latestNormalized)
return &VersionInfo{
Local: localNormalized,
Latest: latestNormalized,
UpToDate: up,
RawLocal: rawLocal,
RawLatest: latest,
}, nil
}
// fetchLatestFromGitHub queries the GitHub API for Docker’s latest release.
// Tries docker/docker-ce, then moby/moby as fallback.
func fetchLatestFromGitHub() (string, error) {
// Try docker-ce first
tag, err := getTagFromGitHub("docker", "docker-ce")
if err == nil && tag != "" {
return tag, nil
}
// Fallback: moby/moby
tag, err = getTagFromGitHub("moby", "moby")
if err == nil && tag != "" {
return tag, nil
}
return "", fmt.Errorf("could not fetch from docker-ce or moby: %v", err)
}
// getTagFromGitHub makes an API call to fetch the latest release tag name.
func getTagFromGitHub(owner, repo string) (string, error) {
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", owner, repo)
body, err := httpGetExternal(url)
if err != nil {
return "", err
}
var res struct {
TagName string `json:"tag_name"`
Name string `json:"name"`
}
if err := json.Unmarshal(body, &res); err != nil {
return "", err
}
if res.TagName != "" {
return res.TagName, nil
}
if res.Name != "" {
return res.Name, nil
}
return "", fmt.Errorf("no tag_name or name found in github response")
}
// PingDocker checks if Docker is reachable and responding.
func (c *Client) PingDocker() error {
_, err := c.httpGetBytes("/_ping")
return err
}
// WaitForDocker waits until Docker daemon responds, with retries.
func (c *Client) WaitForDocker(timeout time.Duration) error {
start := time.Now()
for {
if err := c.PingDocker(); err == nil {
return nil
}
if time.Since(start) > timeout {
return fmt.Errorf("docker daemon not responding after %s", timeout)
}
time.Sleep(2 * time.Second)
}
}