-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautoupdate.go
123 lines (111 loc) · 2.9 KB
/
autoupdate.go
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
"encoding/json"
"strconv"
"k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
type ContainerInfo struct {
Name string
Image string
Tag string
}
type DeploymentInfo struct {
Deployment *v1beta1.Deployment
Containers map[string]*ContainerInfo
}
func getDeployment(kubeClient *kubernetes.Clientset, name, namespace string) (*DeploymentInfo, error) {
deployment, err := kubeClient.Extensions().Deployments(namespace).Get(name, v1.GetOptions{})
if err != nil {
return nil, err
}
deploymentInfo := &DeploymentInfo{
Deployment: deployment,
Containers: make(map[string]*ContainerInfo),
}
for _, container := range deployment.Spec.Template.Spec.Containers {
containerInfo := &ContainerInfo{
Name: container.Name,
}
pieces := strings.Split(container.Image, ":")
containerInfo.Image = pieces[0]
if len(pieces) >= 2 {
containerInfo.Tag = pieces[1]
}
deploymentInfo.Containers[containerInfo.Name] = containerInfo
}
return deploymentInfo, nil
}
func readAutoupdateCredential(rootFolder string, credential *AutoUpdateCredential) (string, string, error) {
username := credential.Username
password := credential.Password
if password == "" {
passwordFile := translateFilePath(rootFolder, credential.PasswordFile)
buf, err := ioutil.ReadFile(passwordFile)
if err != nil {
return "", "", err
}
password = string(buf)
}
return username, password, nil
}
func findNewImageTag(image, username, password string) (string, error) {
return findNewImageTagGCR(image, username, password)
}
func findNewImageTagGCR(image, username, password string) (string, error) {
pieces := strings.Split(image, "/")
if len(pieces) != 3 {
return "", fmt.Errorf("invalid image: %q", image)
}
imageUser := pieces[1]
imageName := pieces[2]
url := "https://gcr.io/v2/" + imageUser + "/" + imageName + "/tags/list"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}
req.SetBasicAuth(username, password)
resp, err := http.DefaultTransport.RoundTrip(req)
if err != nil {
return "", err
}
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
gcrTagList := &GCRTagList{}
err = json.Unmarshal(content, gcrTagList)
if err != nil {
return "", err
}
latestTag := ""
var latestTimestamp int64 = 0
for _, manifest := range gcrTagList.Manifest {
timestamp, err := strconv.ParseInt(manifest.TimeCreatedMs, 10, 64)
if err != nil {
return "", err
}
if timestamp <= latestTimestamp {
continue
}
latestTimestamp = timestamp
for _, tag := range manifest.Tag {
if tag != "latest" {
latestTag = tag
}
}
}
return latestTag, nil
}
type GCRTagList struct {
Manifest map[string]GCRTagManifest `json:"manifest"`
}
type GCRTagManifest struct {
Tag []string `json:"tag"`
TimeCreatedMs string `json:"timeCreatedMs"`
}