Skip to content

Commit ae0ffa3

Browse files
authored
Merge pull request #217 from nginx/208-additional-info-ihealth
Fix: Include platform info in the manifest for iHealth
2 parents 41a9a76 + 1548b80 commit ae0ffa3

File tree

3 files changed

+131
-13
lines changed

3 files changed

+131
-13
lines changed

pkg/data_collector/data_collector.go

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import (
3434

3535
helmClient "github.com/mittwald/go-helm-client"
3636
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/crds"
37-
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/version"
3837
corev1 "k8s.io/api/core/v1"
3938
crdClient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
4039
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -94,12 +93,14 @@ type CommandTiming struct {
9493
type ProductInfo struct {
9594
Product string `json:"product"`
9695
Version string `json:"version"`
96+
Build string `json:"build"`
9797
}
9898

9999
type PlatformInfo struct {
100100
// Add platform-specific fields as needed
101-
K8sVersion string `json:"k8s_version,omitempty"`
102-
Namespaces []string `json:"namespaces,omitempty"`
101+
PlatformType string `json:"platform_type,omitempty"`
102+
Hostname string `json:"hostname,omitempty"`
103+
SerialNumber string `json:"serial_number,omitempty"`
103104
}
104105

105106
type SubPackage struct {
@@ -328,22 +329,43 @@ func (c *DataCollector) AllNamespacesExist() bool {
328329
}
329330

330331
func (c *DataCollector) GenerateManifest(product string, startTime time.Time, jobsRun, jobsFailed int, jobTimings []JobInfo) ([]byte, error) {
332+
// Read and parse product_info.json
333+
filename := filepath.Join(c.BaseDir, "product_info.json")
334+
file, err := os.Open(filename)
335+
var info ProductInfo
336+
if err != nil {
337+
c.Logger.Printf("Warning: failed to open product_info.json: %v. Using default values.", err)
338+
} else {
339+
defer file.Close()
340+
decoder := json.NewDecoder(file)
341+
if err := decoder.Decode(&info); err != nil {
342+
c.Logger.Printf("Warning: failed to decode product_info.json: %v. Using default values.", err)
343+
}
344+
}
345+
346+
filename = filepath.Join(c.BaseDir, "platform_info.json")
347+
file, err = os.Open(filename)
348+
var platformInfo PlatformInfo
349+
if err != nil {
350+
c.Logger.Printf("Warning: failed to open platform_info.json: %v. Using default values.", err)
351+
} else {
352+
defer file.Close()
353+
decoder := json.NewDecoder(file)
354+
if err = decoder.Decode(&platformInfo); err != nil {
355+
c.Logger.Printf("Warning: failed to decode platform_info.json: %v. Using default values.", err)
356+
}
357+
}
331358
manifest := Manifest{
332359
Version: "1.2", // Match the schema version
333360
Timestamp: TimestampInfo{
334361
Start: startTime.UTC().Format(time.RFC3339Nano),
335362
Stop: time.Now().UTC().Format(time.RFC3339Nano),
336363
},
337-
PackageType: "root", // As defined in schema enum
338-
RootDir: ".",
339-
ProductInfo: ProductInfo{
340-
Product: product,
341-
Version: version.Version,
342-
},
343-
PlatformInfo: PlatformInfo{
344-
Namespaces: c.Namespaces,
345-
},
346-
Commands: []Command{},
364+
PackageType: "root", // As defined in schema enum
365+
RootDir: ".",
366+
ProductInfo: info,
367+
PlatformInfo: platformInfo,
368+
Commands: []Command{},
347369
}
348370

349371
// Convert job timings to commands format

pkg/jobs/common_job_list.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,42 @@ func CommonJobList() []Job {
433433
} else {
434434
jsonResult, _ := json.MarshalIndent(result, "", " ")
435435
jobResult.Files[filepath.Join(dc.BaseDir, "k8s", "nodes.json")] = jsonResult
436+
nodeList := result
437+
438+
var hostname string
439+
var platformType string
440+
for _, node := range nodeList.Items {
441+
labels := node.ObjectMeta.Labels
442+
// If the node does NOT have the control-plane label, include its name
443+
if _, exists := labels["node-role.kubernetes.io/control-plane"]; exists {
444+
hostname = node.ObjectMeta.Name
445+
osImage := node.Status.NodeInfo.OSImage
446+
osType := node.Status.NodeInfo.OperatingSystem
447+
osArch := node.Status.NodeInfo.Architecture
448+
449+
platformType = fmt.Sprintf("%s %s/%s", osImage, osType, osArch)
450+
break
451+
}
452+
}
453+
const platformInfoFilename = "platform_info.json"
454+
versionInfo, err := dc.K8sCoreClientSet.Discovery().ServerVersion()
455+
k8sVersion := ""
456+
if err == nil && versionInfo != nil {
457+
k8sVersion = versionInfo.GitVersion
458+
}
459+
460+
platformInfo := data_collector.PlatformInfo{
461+
PlatformType: fmt.Sprintf("%s, k8s version: %s", platformType, k8sVersion),
462+
Hostname: hostname,
463+
SerialNumber: "N/A",
464+
}
465+
466+
platformInfoBytes, err := json.MarshalIndent(platformInfo, "", " ")
467+
if err != nil {
468+
dc.Logger.Printf("\tCould not marshal platformInfo: %v\n", err)
469+
} else {
470+
jobResult.Files[filepath.Join(dc.BaseDir, platformInfoFilename)] = platformInfoBytes
471+
}
436472
}
437473
ch <- jobResult
438474
},

pkg/jobs/nic_job_list.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"encoding/json"
2525
"fmt"
2626
"path/filepath"
27+
"regexp"
2728
"strings"
2829
"time"
2930

@@ -32,6 +33,27 @@ import (
3233
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3334
)
3435

36+
// Extracts ProductInfo from nginx-ingress --version output
37+
func ParseNginxIngressProductInfo(res []byte) data_collector.ProductInfo {
38+
productInfo := data_collector.ProductInfo{
39+
Version: "unknown",
40+
Product: "NGINX Ingress Controller",
41+
Build: "unknown",
42+
}
43+
44+
re := regexp.MustCompile(`Version=([^\s]+)`)
45+
matches := re.FindSubmatch(res)
46+
if len(matches) > 1 {
47+
productInfo.Version = string(matches[1])
48+
}
49+
re = regexp.MustCompile(`Commit=([^\s]+)`)
50+
matches = re.FindSubmatch(res)
51+
if len(matches) > 1 {
52+
productInfo.Build = string(matches[1])
53+
}
54+
return productInfo
55+
}
56+
3557
func NICJobList() []Job {
3658
jobList := []Job{
3759
{
@@ -182,6 +204,44 @@ func NICJobList() []Job {
182204
ch <- jobResult
183205
},
184206
},
207+
{
208+
Name: "collect-product-platform-info",
209+
Timeout: time.Second * 10,
210+
Execute: func(dc *data_collector.DataCollector, ctx context.Context, ch chan JobResult) {
211+
jobResult := JobResult{Files: make(map[string][]byte), Error: nil}
212+
command := []string{"./nginx-ingress", "--version"}
213+
for _, namespace := range dc.Namespaces {
214+
pods, err := dc.K8sCoreClientSet.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{})
215+
if err != nil {
216+
dc.Logger.Printf("\tCould not retrieve pod list for namespace %s: %v\n", namespace, err)
217+
} else {
218+
for _, pod := range pods.Items {
219+
if strings.Contains(pod.Name, "ingress") {
220+
for _, container := range pod.Spec.Containers {
221+
if container.Name == "nginx-ingress" {
222+
res, err := dc.PodExecutor(namespace, pod.Name, container.Name, command, ctx)
223+
if err != nil {
224+
jobResult.Error = err
225+
dc.Logger.Printf("\tCommand execution %s failed for pod %s in namespace %s: %v\n", command, pod.Name, namespace, err)
226+
} else {
227+
productInfo := ParseNginxIngressProductInfo(res)
228+
fileName := "product_info.json"
229+
jsonBytes, err := json.MarshalIndent(productInfo, "", " ")
230+
if err != nil {
231+
jobResult.Error = err
232+
} else {
233+
jobResult.Files[filepath.Join(dc.BaseDir, fileName)] = jsonBytes
234+
}
235+
ch <- jobResult
236+
}
237+
}
238+
}
239+
}
240+
}
241+
}
242+
}
243+
},
244+
},
185245
}
186246
return jobList
187247
}

0 commit comments

Comments
 (0)