Skip to content

Commit e875ba9

Browse files
authored
Merge pull request #159 from nginx/nim-integration
Nim integration
2 parents f6bccc5 + cb06b54 commit e875ba9

File tree

5 files changed

+433
-57
lines changed

5 files changed

+433
-57
lines changed

cmd/nginx-supportpkg.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ import (
3131

3232
func Execute() {
3333

34-
var namespaces []string
3534
var product string
3635
var jobList []jobs.Job
36+
collector := data_collector.DataCollector{}
3737

3838
var rootCmd = &cobra.Command{
3939
Use: "nginx-supportpkg",
4040
Short: "nginx-supportpkg - a tool to create Ingress Controller diagnostics package",
4141
Long: `nginx-supportpkg - a tool to create Ingress Controller diagnostics package`,
4242
Run: func(cmd *cobra.Command, args []string) {
4343

44-
collector, err := data_collector.NewDataCollector(namespaces...)
44+
err := data_collector.NewDataCollector(&collector)
4545
if err != nil {
4646
fmt.Println(fmt.Errorf("unable to start data collector: %s", err))
4747
os.Exit(1)
@@ -57,21 +57,25 @@ func Execute() {
5757
jobList = slices.Concat(jobs.CommonJobList(), jobs.NGFJobList())
5858
case "ngx":
5959
jobList = slices.Concat(jobs.CommonJobList(), jobs.NGXJobList())
60+
case "nim":
61+
jobList = slices.Concat(jobs.CommonJobList(), jobs.NIMJobList())
6062
default:
61-
fmt.Printf("Error: product must be in the following list: [nic, ngf, ngx]\n")
63+
fmt.Printf("Error: product must be in the following list: [nic, ngf, ngx, nim]\n")
6264
os.Exit(1)
6365
}
6466

6567
if collector.AllNamespacesExist() {
6668
failedJobs := 0
6769
for _, job := range jobList {
6870
fmt.Printf("Running job %s...", job.Name)
69-
err = job.Collect(collector)
70-
if err != nil {
71-
fmt.Printf(" Error: %s\n", err)
71+
err, Skipped := job.Collect(&collector)
72+
if Skipped {
73+
fmt.Print(" SKIPPED\n")
74+
} else if err != nil {
75+
fmt.Printf(" FAILED: %s\n", err)
7276
failedJobs++
7377
} else {
74-
fmt.Print(" OK\n")
78+
fmt.Print(" COMPLETED\n")
7579
}
7680
}
7781

@@ -94,7 +98,7 @@ func Execute() {
9498
},
9599
}
96100

97-
rootCmd.Flags().StringSliceVarP(&namespaces, "namespace", "n", []string{}, "list of namespaces to collect information from")
101+
rootCmd.Flags().StringSliceVarP(&collector.Namespaces, "namespace", "n", []string{}, "list of namespaces to collect information from")
98102
if err := rootCmd.MarkFlagRequired("namespace"); err != nil {
99103
fmt.Println(err)
100104
os.Exit(1)
@@ -106,6 +110,9 @@ func Execute() {
106110
os.Exit(1)
107111
}
108112

113+
rootCmd.Flags().BoolVarP(&collector.ExcludeDBData, "exclude-db-data", "d", false, "exclude DB data collection")
114+
rootCmd.Flags().BoolVarP(&collector.ExcludeTimeSeriesData, "exclude-time-series-data", "t", false, "exclude time series data collection")
115+
109116
versionStr := "nginx-supportpkg - version: " + version.Version + " - build: " + version.Build + "\n"
110117
rootCmd.SetVersionTemplate(versionStr)
111118
rootCmd.Version = versionStr
@@ -115,8 +122,9 @@ func Execute() {
115122
"Usage:" +
116123
"\n nginx-supportpkg -h|--help" +
117124
"\n nginx-supportpkg -v|--version" +
118-
"\n nginx-supportpkg [-n|--namespace] ns1 [-n|--namespace] ns2 [-p|--product] [nic,ngf,ngx]" +
119-
"\n nginx-supportpkg [-n|--namespace] ns1,ns2 [-p|--product] [nic,ngf,ngx] \n")
125+
"\n nginx-supportpkg [-n|--namespace] ns1 [-n|--namespace] ns2 [-p|--product] [nic,ngf,ngx,nim]" +
126+
"\n nginx-supportpkg [-n|--namespace] ns1,ns2 [-p|--product] [nic,ngf,ngx,nim]" +
127+
"\n nginx-supportpkg [-n|--namespace] ns1 [-n|--namespace] ns2 [-p|--product] [nim] [-d|--exclude-db-data] [-t|--exclude-time-series-data] \n")
120128

121129
if err := rootCmd.Execute(); err != nil {
122130
fmt.Println(err)

pkg/data_collector/data_collector.go

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ import (
2424
"compress/gzip"
2525
"context"
2626
"fmt"
27+
"io"
28+
"log"
29+
"os"
30+
"path/filepath"
31+
"strconv"
32+
"time"
33+
2734
helmClient "github.com/mittwald/go-helm-client"
2835
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/crds"
29-
"io"
3036
corev1 "k8s.io/api/core/v1"
3137
crdClient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
3238
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -38,35 +44,32 @@ import (
3844
"k8s.io/client-go/tools/remotecommand"
3945
"k8s.io/client-go/util/homedir"
4046
metricsClient "k8s.io/metrics/pkg/client/clientset/versioned"
41-
"log"
42-
"os"
43-
"path/filepath"
44-
"strconv"
45-
"time"
4647
)
4748

4849
type DataCollector struct {
49-
BaseDir string
50-
Namespaces []string
51-
Logger *log.Logger
52-
LogFile *os.File
53-
K8sRestConfig *rest.Config
54-
K8sCoreClientSet *kubernetes.Clientset
55-
K8sCrdClientSet *crdClient.Clientset
56-
K8sMetricsClientSet *metricsClient.Clientset
57-
K8sHelmClientSet map[string]helmClient.Client
50+
BaseDir string
51+
Namespaces []string
52+
Logger *log.Logger
53+
LogFile *os.File
54+
K8sRestConfig *rest.Config
55+
K8sCoreClientSet *kubernetes.Clientset
56+
K8sCrdClientSet *crdClient.Clientset
57+
K8sMetricsClientSet *metricsClient.Clientset
58+
K8sHelmClientSet map[string]helmClient.Client
59+
ExcludeDBData bool
60+
ExcludeTimeSeriesData bool
5861
}
5962

60-
func NewDataCollector(namespaces ...string) (*DataCollector, error) {
63+
func NewDataCollector(collector *DataCollector) error {
6164

6265
tmpDir, err := os.MkdirTemp("", "-pkg-diag")
6366
if err != nil {
64-
return nil, fmt.Errorf("unable to create temp directory: %s", err)
67+
return fmt.Errorf("unable to create temp directory: %s", err)
6568
}
6669

6770
logFile, err := os.OpenFile(filepath.Join(tmpDir, "supportpkg.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
6871
if err != nil {
69-
return nil, fmt.Errorf("unable to create log file: %s", err)
72+
return fmt.Errorf("unable to create log file: %s", err)
7073
}
7174

7275
// Find config
@@ -77,30 +80,27 @@ func NewDataCollector(namespaces ...string) (*DataCollector, error) {
7780
config, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
7881

7982
if err != nil {
80-
return nil, fmt.Errorf("unable to connect to k8s using file %s: %s", kubeConfig, err)
81-
}
82-
83-
dc := DataCollector{
84-
BaseDir: tmpDir,
85-
Namespaces: namespaces,
86-
LogFile: logFile,
87-
Logger: log.New(logFile, "", log.LstdFlags|log.LUTC|log.Lmicroseconds|log.Lshortfile),
88-
K8sHelmClientSet: make(map[string]helmClient.Client),
83+
return fmt.Errorf("unable to connect to k8s using file %s: %s", kubeConfig, err)
8984
}
85+
// Set up the DataCollector options
86+
collector.BaseDir = tmpDir
87+
collector.LogFile = logFile
88+
collector.Logger = log.New(logFile, "", log.LstdFlags|log.LUTC|log.Lmicroseconds|log.Lshortfile)
89+
collector.K8sHelmClientSet = make(map[string]helmClient.Client)
9090

9191
//Initialize clients
92-
dc.K8sRestConfig = config
93-
dc.K8sCoreClientSet, _ = kubernetes.NewForConfig(config)
94-
dc.K8sCrdClientSet, _ = crdClient.NewForConfig(config)
95-
dc.K8sMetricsClientSet, _ = metricsClient.NewForConfig(config)
96-
for _, namespace := range dc.Namespaces {
97-
dc.K8sHelmClientSet[namespace], _ = helmClient.NewClientFromRestConf(&helmClient.RestConfClientOptions{
92+
collector.K8sRestConfig = config
93+
collector.K8sCoreClientSet, _ = kubernetes.NewForConfig(config)
94+
collector.K8sCrdClientSet, _ = crdClient.NewForConfig(config)
95+
collector.K8sMetricsClientSet, _ = metricsClient.NewForConfig(config)
96+
for _, namespace := range collector.Namespaces {
97+
collector.K8sHelmClientSet[namespace], _ = helmClient.NewClientFromRestConf(&helmClient.RestConfClientOptions{
9898
Options: &helmClient.Options{Namespace: namespace},
9999
RestConfig: config,
100100
})
101101
}
102102

103-
return &dc, nil
103+
return nil
104104
}
105105

106106
func (c *DataCollector) WrapUp(product string) (string, error) {

pkg/jobs/common_job_list.go

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ import (
2323
"context"
2424
"encoding/json"
2525
"fmt"
26-
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/data_collector"
2726
"io"
28-
corev1 "k8s.io/api/core/v1"
29-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3027
"path/filepath"
3128
"time"
29+
30+
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/data_collector"
31+
corev1 "k8s.io/api/core/v1"
32+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3233
)
3334

3435
func CommonJobList() []Job {
@@ -88,6 +89,91 @@ func CommonJobList() []Job {
8889
ch <- jobResult
8990
},
9091
},
92+
{
93+
Name: "pv-list",
94+
Timeout: time.Second * 10,
95+
Execute: func(dc *data_collector.DataCollector, ctx context.Context, ch chan JobResult) {
96+
jobResult := JobResult{Files: make(map[string][]byte), Error: nil}
97+
for _, namespace := range dc.Namespaces {
98+
result, err := dc.K8sCoreClientSet.CoreV1().PersistentVolumes().List(ctx, metav1.ListOptions{})
99+
if err != nil {
100+
dc.Logger.Printf("\tCould not retrieve persistent volumes list %s: %v\n", namespace, err)
101+
} else {
102+
jsonResult, _ := json.MarshalIndent(result, "", " ")
103+
jobResult.Files[filepath.Join(dc.BaseDir, "resources", namespace, "persistentvolumes.json")] = jsonResult
104+
}
105+
}
106+
ch <- jobResult
107+
},
108+
},
109+
{
110+
Name: "pvc-list",
111+
Timeout: time.Second * 10,
112+
Execute: func(dc *data_collector.DataCollector, ctx context.Context, ch chan JobResult) {
113+
jobResult := JobResult{Files: make(map[string][]byte), Error: nil}
114+
for _, namespace := range dc.Namespaces {
115+
result, err := dc.K8sCoreClientSet.CoreV1().PersistentVolumeClaims(namespace).List(ctx, metav1.ListOptions{})
116+
if err != nil {
117+
dc.Logger.Printf("\tCould not retrieve persistent volume claims list %s: %v\n", namespace, err)
118+
} else {
119+
jsonResult, _ := json.MarshalIndent(result, "", " ")
120+
jobResult.Files[filepath.Join(dc.BaseDir, "resources", namespace, "persistentvolumeclaims.json")] = jsonResult
121+
}
122+
}
123+
ch <- jobResult
124+
},
125+
},
126+
{
127+
Name: "sc-list",
128+
Timeout: time.Second * 10,
129+
Execute: func(dc *data_collector.DataCollector, ctx context.Context, ch chan JobResult) {
130+
jobResult := JobResult{Files: make(map[string][]byte), Error: nil}
131+
for _, namespace := range dc.Namespaces {
132+
result, err := dc.K8sCoreClientSet.StorageV1().StorageClasses().List(ctx, metav1.ListOptions{})
133+
if err != nil {
134+
dc.Logger.Printf("\tCould not retrieve storage classes list %s: %v\n", namespace, err)
135+
} else {
136+
jsonResult, _ := json.MarshalIndent(result, "", " ")
137+
jobResult.Files[filepath.Join(dc.BaseDir, "resources", namespace, "storageclasses.json")] = jsonResult
138+
}
139+
}
140+
ch <- jobResult
141+
},
142+
},
143+
{
144+
Name: "apiresources-list",
145+
Timeout: time.Second * 10,
146+
Execute: func(dc *data_collector.DataCollector, ctx context.Context, ch chan JobResult) {
147+
jobResult := JobResult{Files: make(map[string][]byte), Error: nil}
148+
for _, namespace := range dc.Namespaces {
149+
result, err := dc.K8sCoreClientSet.DiscoveryClient.ServerPreferredResources()
150+
if err != nil {
151+
dc.Logger.Printf("\tCould not retrieve API resources list %s: %v\n", namespace, err)
152+
} else {
153+
jsonResult, _ := json.MarshalIndent(result, "", " ")
154+
jobResult.Files[filepath.Join(dc.BaseDir, "resources", namespace, "apiresources.json")] = jsonResult
155+
}
156+
}
157+
ch <- jobResult
158+
},
159+
},
160+
{
161+
Name: "apiversions-list",
162+
Timeout: time.Second * 10,
163+
Execute: func(dc *data_collector.DataCollector, ctx context.Context, ch chan JobResult) {
164+
jobResult := JobResult{Files: make(map[string][]byte), Error: nil}
165+
for _, namespace := range dc.Namespaces {
166+
result, err := dc.K8sCoreClientSet.DiscoveryClient.ServerGroups()
167+
if err != nil {
168+
dc.Logger.Printf("\tCould not retrieve API versions list %s: %v\n", namespace, err)
169+
} else {
170+
jsonResult, _ := json.MarshalIndent(result, "", " ")
171+
jobResult.Files[filepath.Join(dc.BaseDir, "resources", namespace, "apiversions.json")] = jsonResult
172+
}
173+
}
174+
ch <- jobResult
175+
},
176+
},
91177
{
92178
Name: "events-list",
93179
Timeout: time.Second * 10,

pkg/jobs/job.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ package jobs
2020

2121
import (
2222
"context"
23-
"errors"
2423
"fmt"
25-
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/data_collector"
2624
"os"
2725
"path/filepath"
2826
"time"
27+
28+
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/data_collector"
2929
)
3030

3131
type Job struct {
@@ -35,11 +35,12 @@ type Job struct {
3535
}
3636

3737
type JobResult struct {
38-
Files map[string][]byte
39-
Error error
38+
Files map[string][]byte
39+
Error error
40+
Skipped bool
4041
}
4142

42-
func (j Job) Collect(dc *data_collector.DataCollector) error {
43+
func (j Job) Collect(dc *data_collector.DataCollector) (error, bool) {
4344
ch := make(chan JobResult, 1)
4445

4546
ctx, cancel := context.WithTimeout(context.Background(), j.Timeout)
@@ -51,28 +52,32 @@ func (j Job) Collect(dc *data_collector.DataCollector) error {
5152
select {
5253
case <-ctx.Done():
5354
dc.Logger.Printf("\tJob %s has timed out: %s\n---\n", j.Name, ctx.Err())
54-
return errors.New(fmt.Sprintf("Context cancelled: %v", ctx.Err()))
55+
return fmt.Errorf("Context cancelled: %v", ctx.Err()), false
5556

5657
case jobResults := <-ch:
58+
if jobResults.Skipped {
59+
dc.Logger.Printf("\tJob %s has been skipped\n---\n", j.Name)
60+
return nil, true
61+
}
5762
if jobResults.Error != nil {
5863
dc.Logger.Printf("\tJob %s has failed: %s\n", j.Name, jobResults.Error)
59-
return jobResults.Error
64+
return jobResults.Error, false
6065
}
6166

6267
for fileName, fileValue := range jobResults.Files {
6368
err := os.MkdirAll(filepath.Dir(fileName), os.ModePerm)
6469
if err != nil {
65-
return fmt.Errorf("MkdirAll failed: %v", err)
70+
return fmt.Errorf("MkdirAll failed: %v", err), jobResults.Skipped
6671
}
6772
file, _ := os.Create(fileName)
6873
_, err = file.Write(fileValue)
6974
if err != nil {
70-
return fmt.Errorf("Write failed: %v", err)
75+
return fmt.Errorf("Write failed: %v", err), jobResults.Skipped
7176
}
7277
_ = file.Close()
7378
dc.Logger.Printf("\tJob %s wrote %d bytes to %s\n", j.Name, len(fileValue), fileName)
7479
}
7580
dc.Logger.Printf("\tJob %s completed successfully\n---\n", j.Name)
76-
return nil
81+
return nil, jobResults.Skipped
7782
}
7883
}

0 commit comments

Comments
 (0)