Skip to content

Commit aca4bd3

Browse files
authored
Merge pull request #210 from jetstack/update-version-checker
Update version checker data gatherer
2 parents 228e264 + 7be4cb8 commit aca4bd3

File tree

8 files changed

+135
-33
lines changed

8 files changed

+135
-33
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ require (
1919
github.com/googleapis/gnostic v0.5.1 // indirect
2020
github.com/hashicorp/go-multierror v1.0.0
2121
github.com/imdario/mergo v0.3.11 // indirect
22-
github.com/jetstack/version-checker v0.2.1
22+
github.com/jetstack/version-checker v0.2.2-0.20201118163251-4bab9ef088ef
2323
github.com/juju/errors v0.0.0-20190930114154-d42613fe1ab9
2424
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
2525
github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ github.com/jarcoal/httpmock v1.0.1 h1:OXIOrglWeSllwHQGJ5X4PX4hFZK1DPCXSJVhMSJacg
295295
github.com/jarcoal/httpmock v1.0.1/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
296296
github.com/jetstack/version-checker v0.2.1 h1:fTkj1ztb6WP4gMQTROHYAUHJMFMuZOBRRLMrZa0bed4=
297297
github.com/jetstack/version-checker v0.2.1/go.mod h1:908YLy8SWIJMJoYQpZf2QIRAvBvZ2WM0ylNiCrK8Vvg=
298+
github.com/jetstack/version-checker v0.2.2-0.20201118163251-4bab9ef088ef h1:bsZIh0Y7TogJfmseOARM9OeZzctSDuuHuJQTQhl97Mo=
299+
github.com/jetstack/version-checker v0.2.2-0.20201118163251-4bab9ef088ef/go.mod h1:908YLy8SWIJMJoYQpZf2QIRAvBvZ2WM0ylNiCrK8Vvg=
298300
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
299301
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
300302
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
22
"schemaVersion": 1,
33
"name": "jetstack/example",
4-
"tag": "v1.0.0"
4+
"tag": "v1.0.0",
5+
"architecture":"amd64",
6+
"os":""
57
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
22
"schemaVersion": 1,
33
"name": "jetstack/example",
4-
"tag": "v1.0.1"
4+
"tag": "v1.0.1",
5+
"architecture":"amd64",
6+
"os":""
57
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"apiVersion": "v1",
3+
"kind": "List",
4+
"metadata": {
5+
"resourceVersion": "",
6+
"selfLink": ""
7+
},
8+
"items": [
9+
{
10+
"apiVersion": "v1",
11+
"kind": "Node",
12+
"metadata": {
13+
"creationTimestamp": "2020-11-24T16:04:38Z",
14+
"labels": {
15+
"beta.kubernetes.io/arch": "amd64",
16+
"beta.kubernetes.io/os": "",
17+
"kubernetes.io/arch": "amd64",
18+
"kubernetes.io/hostname": "control-plane",
19+
"kubernetes.io/os": ""
20+
},
21+
"name": "control-plane",
22+
"resourceVersion": "167265",
23+
"selfLink": "/api/v1/nodes/control-plane",
24+
"uid": "d966826d-e63c-487c-a769-cb02098b95fd"
25+
},
26+
"spec": {},
27+
"status": {}
28+
}
29+
]
30+
}

pkg/datagatherer/versionchecker/fixtures/pods.json.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"uid": "efff9dae-28ca-42c3-be70-970731c44f67"
3232
},
3333
"spec": {
34+
"nodeName": "control-plane",
3435
"containers": [
3536
{
3637
"name": "example",

pkg/datagatherer/versionchecker/versionchecker.go

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import (
1010
"time"
1111

1212
vcapi "github.com/jetstack/version-checker/pkg/api"
13+
vcchecker "github.com/jetstack/version-checker/pkg/checker"
14+
vcarchitecture "github.com/jetstack/version-checker/pkg/checker/architecture"
15+
vcsearch "github.com/jetstack/version-checker/pkg/checker/search"
16+
vcversion "github.com/jetstack/version-checker/pkg/checker/version"
1317
vcclient "github.com/jetstack/version-checker/pkg/client"
1418
vcselfhosted "github.com/jetstack/version-checker/pkg/client/selfhosted"
15-
vcchecker "github.com/jetstack/version-checker/pkg/controller/checker"
16-
vcsearch "github.com/jetstack/version-checker/pkg/controller/search"
17-
vcversion "github.com/jetstack/version-checker/pkg/version"
1819
"github.com/sirupsen/logrus"
1920
v1 "k8s.io/api/core/v1"
2021
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -53,7 +54,9 @@ const (
5354
type Config struct {
5455
// the version checker dg will also gather pods and so has the same options
5556
// as the dynamic datagatherer
56-
Dynamic k8s.ConfigDynamic
57+
DynamicPod k8s.ConfigDynamic
58+
// the nodes information is also gathered by the version checker datagatherer
59+
DynamicNode k8s.ConfigDynamic
5760
VersionCheckerClientOptions vcclient.Options
5861
// Currently unused, but keeping to allow future config of VersionChecker
5962
VersionCheckerCheckerOptions vcapi.Options
@@ -77,13 +80,20 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
7780
return fmt.Errorf("failed to unmarshal version checker config: %s", err)
7881
}
7982

80-
c.Dynamic.KubeConfigPath = aux.Dynamic.KubeConfigPath
81-
c.Dynamic.ExcludeNamespaces = aux.Dynamic.ExcludeNamespaces
82-
c.Dynamic.IncludeNamespaces = aux.Dynamic.IncludeNamespaces
83+
c.DynamicPod.KubeConfigPath = aux.Dynamic.KubeConfigPath
84+
c.DynamicPod.ExcludeNamespaces = aux.Dynamic.ExcludeNamespaces
85+
c.DynamicPod.IncludeNamespaces = aux.Dynamic.IncludeNamespaces
8386
// gvr must be pods for the version checker dg
84-
c.Dynamic.GroupVersionResource.Group = ""
85-
c.Dynamic.GroupVersionResource.Version = "v1"
86-
c.Dynamic.GroupVersionResource.Resource = "pods"
87+
c.DynamicPod.GroupVersionResource.Group = ""
88+
c.DynamicPod.GroupVersionResource.Version = "v1"
89+
c.DynamicPod.GroupVersionResource.Resource = "pods"
90+
// node dynamic dg
91+
c.DynamicNode.KubeConfigPath = aux.Dynamic.KubeConfigPath
92+
c.DynamicNode.ExcludeNamespaces = []string{}
93+
c.DynamicNode.IncludeNamespaces = []string{}
94+
c.DynamicNode.GroupVersionResource.Group = ""
95+
c.DynamicNode.GroupVersionResource.Version = "v1"
96+
c.DynamicNode.GroupVersionResource.Resource = "nodes"
8797

8898
c.VersionCheckerClientOptions.Selfhosted = map[string]*vcselfhosted.Options{}
8999
registryKindCounts := map[string]int{}
@@ -200,7 +210,12 @@ func loadKeysFromPaths(keys []string, params map[string]string) (map[string]stri
200210
// NewDataGatherer creates a new VersionChecker DataGatherer
201211
func (c *Config) NewDataGatherer(ctx context.Context) (datagatherer.DataGatherer, error) {
202212
// create the k8s DataGatherer to use when collecting pods
203-
dynamicDg, err := c.Dynamic.NewDataGatherer(ctx)
213+
podDynamicDg, err := c.DynamicPod.NewDataGatherer(ctx)
214+
if err != nil {
215+
return nil, err
216+
}
217+
// create a data gatherer to use to collect nodes architecture information
218+
nodeDynamicDg, err := c.DynamicNode.NewDataGatherer(ctx)
204219
if err != nil {
205220
return nil, err
206221
}
@@ -219,13 +234,16 @@ func (c *Config) NewDataGatherer(ctx context.Context) (datagatherer.DataGatherer
219234
timeout,
220235
vcversion.New(log, imageClient, timeout),
221236
)
237+
architecture := vcarchitecture.New()
222238

223239
// dg wraps version checker and dynamic client to request pods
224240
return &DataGatherer{
225241
ctx: ctx,
226242
config: c,
227-
dynamicDg: dynamicDg,
228-
versionChecker: vcchecker.New(search),
243+
podDynamicDg: podDynamicDg,
244+
nodeDynamicDg: nodeDynamicDg,
245+
nodeArchitecture: architecture,
246+
versionChecker: vcchecker.New(search, architecture),
229247
versionCheckerLog: log,
230248
versionCheckerOptions: c.VersionCheckerCheckerOptions,
231249
}, nil
@@ -235,7 +253,9 @@ func (c *Config) NewDataGatherer(ctx context.Context) (datagatherer.DataGatherer
235253
type DataGatherer struct {
236254
ctx context.Context
237255
config *Config
238-
dynamicDg datagatherer.DataGatherer
256+
podDynamicDg datagatherer.DataGatherer
257+
nodeDynamicDg datagatherer.DataGatherer
258+
nodeArchitecture *vcarchitecture.NodeMap
239259
versionChecker *vcchecker.Checker
240260
versionCheckerLog *logrus.Entry
241261
versionCheckerOptions vcapi.Options
@@ -257,9 +277,31 @@ type containerResult struct {
257277

258278
// Fetch retrieves cluster information from GKE.
259279
func (g *DataGatherer) Fetch() (interface{}, error) {
260-
rawPods, err := g.dynamicDg.Fetch()
280+
// Get nodes information to update version-checker architecture structure
281+
rawNodes, err := g.nodeDynamicDg.Fetch()
261282
if err != nil {
262-
return nil, err
283+
return nil, fmt.Errorf("failed to fetch nodes: %v", err)
284+
}
285+
nodes, ok := rawNodes.(*unstructured.UnstructuredList)
286+
if !ok {
287+
return nil, fmt.Errorf("failed to parse nodes loaded from DataGatherer")
288+
}
289+
for _, v := range nodes.Items {
290+
var node v1.Node
291+
err := runtime.DefaultUnstructuredConverter.FromUnstructured(v.Object, &node)
292+
if err != nil {
293+
return nil, fmt.Errorf("failed to parse node from unstructured data: %v", err)
294+
}
295+
// update version-checker's internal representation of the current cluster's nodes,
296+
// to correctly select the right OS and Architecture for the images
297+
if err = g.nodeArchitecture.Add(&node); err != nil {
298+
return nil, fmt.Errorf("failed to add node to version-checker architecture structure")
299+
}
300+
}
301+
302+
rawPods, err := g.podDynamicDg.Fetch()
303+
if err != nil {
304+
return nil, fmt.Errorf("failed to fetch pods: %v", err)
263305
}
264306

265307
pods, ok := rawPods.(*unstructured.UnstructuredList)
@@ -272,7 +314,7 @@ func (g *DataGatherer) Fetch() (interface{}, error) {
272314
var pod v1.Pod
273315
err = runtime.DefaultUnstructuredConverter.FromUnstructured(v.Object, &pod)
274316
if err != nil {
275-
return nil, fmt.Errorf("failed to parse pod from unstructured data")
317+
return nil, fmt.Errorf("failed to parse pod from unstructured data: %v", err)
276318
}
277319

278320
var allContainers []v1.Container

pkg/datagatherer/versionchecker/versionchecker_test.go

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net/url"
1313
"os"
1414
"reflect"
15+
"regexp"
1516
"testing"
1617

1718
"gopkg.in/yaml.v2"
@@ -78,23 +79,23 @@ registries:
7879
expTarget interface{}
7980
}{
8081
"KubeConfigPath": {
81-
configTarget: cfg.Dynamic.KubeConfigPath,
82+
configTarget: cfg.DynamicPod.KubeConfigPath,
8283
expTarget: "/home/someone/.kube/config",
8384
},
8485
"GVR": {
85-
configTarget: cfg.Dynamic.GroupVersionResource,
86+
configTarget: cfg.DynamicPod.GroupVersionResource,
8687
expTarget: schema.GroupVersionResource{
8788
Group: "",
8889
Version: "v1",
8990
Resource: "pods", // should use pods even if other gvr set
9091
},
9192
},
9293
"IncludeNamespaces": {
93-
configTarget: cfg.Dynamic.IncludeNamespaces,
94+
configTarget: cfg.DynamicPod.IncludeNamespaces,
9495
expTarget: []string{"default"},
9596
},
9697
"ExcludeNamespaces": {
97-
configTarget: cfg.Dynamic.ExcludeNamespaces,
98+
configTarget: cfg.DynamicPod.ExcludeNamespaces,
9899
expTarget: []string{"kube-system"},
99100
},
100101
"GCR Token": {
@@ -173,12 +174,12 @@ registries:
173174

174175
rawResults, err := dg.Fetch()
175176
if err != nil {
176-
t.Fatalf("failed fetch data %s", err)
177+
t.Fatalf("failed fetch data: %s", err)
177178
}
178179

179180
resultsJSON, err := json.MarshalIndent(rawResults, "", " ")
180181
if err != nil {
181-
t.Fatalf("failed to marshal data %s", err)
182+
t.Fatalf("failed to marshal data: %s", err)
182183
}
183184

184185
expectedResultsJSON := fmt.Sprintf(`[
@@ -218,7 +219,8 @@ registries:
218219
],
219220
"resources": {}
220221
}
221-
]
222+
],
223+
"nodeName": "control-plane"
222224
},
223225
"status": {
224226
"containerStatuses": [
@@ -241,16 +243,20 @@ registries:
241243
"result": {
242244
"CurrentVersion": "v1.0.0",
243245
"LatestVersion": "v1.0.1",
244-
"IsLatest": false,
245-
"ImageURL": "%s/jetstack/example"
246+
"IsLatest": false,
247+
"ImageURL": "%s/jetstack/example",
248+
"OS": "",
249+
"Architecture": "amd64"
246250
}
247251
}
248252
]
249253
}
250254
]`, parsedURL.Host, parsedURL.Host)
251255

252-
if expectedResultsJSON != string(resultsJSON) {
253-
t.Fatalf("results json does not match: %s vs %s", resultsJSON, expectedResultsJSON)
256+
act := removeWhitespace(string(resultsJSON))
257+
expected := removeWhitespace(expectedResultsJSON)
258+
if act != expected {
259+
t.Fatalf("results json does not match: %s vs %s", act, expected)
254260
}
255261
}
256262

@@ -319,6 +325,11 @@ func createLocalTestServer(t *testing.T) *httptest.Server {
319325
var err error
320326

321327
switch r.URL.Path {
328+
case "/api/v1/nodes":
329+
responseContent, err = ioutil.ReadFile("fixtures/nodes.json")
330+
if err != nil {
331+
t.Fatalf("failed to read nodes fixture: %s", err)
332+
}
322333
case "/api/v1/pods":
323334
// the responses from the server are self referential and the host is
324335
// needed to generate responses
@@ -347,17 +358,23 @@ func createLocalTestServer(t *testing.T) *httptest.Server {
347358
}
348359
case "/v2/jetstack/example/manifests/v1.0.0":
349360
// this is a partial response, but it's all version checker needs
361+
// selfhosted registers currently don't expose OS information
350362
responseContent = []byte(`{
351363
"schemaVersion": 1,
352364
"name": "jetstack/example",
353-
"tag": "v1.0.0"
365+
"tag": "v1.0.0",
366+
"architecture":"amd64",
367+
"os":""
354368
}`)
355369
case "/v2/jetstack/example/manifests/v1.0.1":
356370
// this is a partial response, but it's all version checker needs
371+
// selfhosted registers currently don't expose OS information
357372
responseContent = []byte(`{
358373
"schemaVersion": 1,
359374
"name": "jetstack/example",
360-
"tag": "v1.0.1"
375+
"tag": "v1.0.1",
376+
"architecture":"amd64",
377+
"os":""
361378
}`)
362379
default:
363380
t.Fatalf("Unexpected URL was called: %s", r.URL.Path)
@@ -368,3 +385,9 @@ func createLocalTestServer(t *testing.T) *httptest.Server {
368385

369386
return localServer
370387
}
388+
389+
// Simple helper function to remove whitespaces from string
390+
func removeWhitespace(input string) string {
391+
ws := regexp.MustCompile(`[\s]`)
392+
return ws.ReplaceAllString(input, "")
393+
}

0 commit comments

Comments
 (0)