Skip to content

Commit dae6f9f

Browse files
authored
Merge pull request #11 from GreatLazyMan/new_feature
title: add multiport check and dns check feature
2 parents 0130f51 + 1c3ad9e commit dae6f9f

File tree

13 files changed

+298
-54
lines changed

13 files changed

+298
-54
lines changed

cluster/images/floater.Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ ARG BINARY
44

55
RUN apk add --no-cache ca-certificates
66
RUN apk update && apk upgrade
7-
RUN apk add ip6tables iptables curl
7+
RUN apk add --no-cache ip6tables iptables curl netcat-openbsd
88

99
COPY ${BINARY} /bin/${BINARY}

pkg/command/check.go

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"fmt"
5+
"strconv"
56

67
"sync"
78

@@ -67,6 +68,10 @@ func (o *CheckOptions) LoadConfig() {
6768
func (o *CheckOptions) Complete() error {
6869
o.LoadConfig()
6970

71+
if o.DoOption == nil {
72+
return fmt.Errorf("config.json load error")
73+
}
74+
7075
srcfloater := &share.Floater{
7176
Namespace: o.DoOption.Namespace,
7277
Name: share.DefaultFloaterName,
@@ -108,6 +113,19 @@ func (o *CheckOptions) Validate() error {
108113
if len(o.DoOption.Namespace) == 0 {
109114
return fmt.Errorf("namespace must be specified")
110115
}
116+
if len(o.DoOption.CustomizedTargetPortList) != 0 {
117+
for _, port := range o.DoOption.CustomizedTargetPortList {
118+
portInt, err := strconv.Atoi(port)
119+
if err != nil {
120+
return fmt.Errorf("invalid port: %s", port)
121+
} else if portInt <= 0 || portInt > 65535 {
122+
return fmt.Errorf("invalid port: %d", portInt)
123+
}
124+
}
125+
if len(o.DoOption.CustomizedTargetIPList) == 0 {
126+
return fmt.Errorf("if CustomizedTargetPortList is not null, CustomizedTargetIPList should be assigned")
127+
}
128+
}
111129

112130
return nil
113131
}

pkg/command/init.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,18 @@ func NewInitCmd() *cobra.Command {
4747

4848
func (o *InitOptions) Run() error {
4949
doOptions := share.DoOptions{
50-
Namespace: utils.DefaultNamespace,
51-
Port: "8889",
52-
PodWaitTime: 30,
53-
Protocol: string(utils.TCP),
54-
MaxNum: 3,
55-
AutoClean: false,
56-
CmdTimeout: 10,
57-
Version: "0.2.1",
50+
Namespace: utils.DefaultNamespace,
51+
Port: "8889",
52+
CustomizedTargetPortList: []string{},
53+
CustomizedTargetIPList: []string{},
54+
TargetDNSServer: "",
55+
TargetHostToLookup: "",
56+
PodWaitTime: 30,
57+
Protocol: string(utils.TCP),
58+
MaxNum: 3,
59+
AutoClean: false,
60+
CmdTimeout: 10,
61+
Version: "0.2.1",
5862
// src
5963
SrcImageRepository: utils.DefaultImageRepository,
6064
SrcKubeConfig: utils.DefaultKubeConfigPath,

pkg/command/resume.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"fmt"
5+
"strconv"
56

67
"github.com/kosmos.io/netdoctor/pkg/command/share"
78
"github.com/kosmos.io/netdoctor/pkg/utils"
@@ -60,6 +61,9 @@ func (o *ResumeOptions) LoadConfig() {
6061

6162
func (o *ResumeOptions) Complete() error {
6263
o.LoadConfig()
64+
if o.DoOption == nil {
65+
return fmt.Errorf("config.json load error")
66+
}
6367

6468
srcfloater := &share.Floater{
6569
Namespace: o.DoOption.Namespace,
@@ -97,7 +101,10 @@ func (o *ResumeOptions) Complete() error {
97101

98102
var resumeData []*share.PrintCheckData
99103

100-
utils.ReadResume(&resumeData)
104+
err := utils.ReadResume(&resumeData)
105+
if err != nil {
106+
klog.Error("read resumeData error")
107+
}
101108

102109
o.DoOption.ResumeRecord = resumeData
103110

@@ -109,6 +116,17 @@ func (o *ResumeOptions) Validate() error {
109116
return fmt.Errorf("namespace must be specified")
110117
}
111118

119+
if len(o.DoOption.CustomizedTargetPortList) != 0 {
120+
for _, port := range o.DoOption.CustomizedTargetPortList {
121+
portInt, err := strconv.Atoi(port)
122+
if err != nil {
123+
return fmt.Errorf("invalid port: %s", port)
124+
} else if portInt <= 0 || portInt > 65535 {
125+
return fmt.Errorf("invalid port: %d", portInt)
126+
}
127+
}
128+
}
129+
112130
return nil
113131
}
114132

pkg/command/share/do.go

+78-26
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@ import (
66

77
command "github.com/kosmos.io/netdoctor/pkg/command/share/remote-command"
88
"github.com/kosmos.io/netdoctor/pkg/utils"
9+
10+
progressbar "github.com/schollz/progressbar/v3"
911
"k8s.io/klog/v2"
1012
)
1113

1214
type DoOptions struct {
1315
Namespace string `json:"namespace,omitempty"`
1416
Version string `json:"version,omitempty"`
1517

16-
Protocol string `json:"protocol,omitempty"`
17-
PodWaitTime int `json:"podWaitTime,omitempty"`
18-
Port string `json:"port,omitempty"`
18+
Protocol string `json:"protocol,omitempty"`
19+
PodWaitTime int `json:"podWaitTime,omitempty"`
20+
Port string `json:"port,omitempty"`
21+
CustomizedTargetPortList []string `json:"customizedTargetPortList,omitempty"`
22+
CustomizedTargetIPList []string `json:"customizedTargetIPList,omitempty"`
23+
TargetDNSServer string `json:"targetDNSServer,omitempty"`
24+
TargetHostToLookup string `json:"targetHostToLookup,omitempty"`
1925

2026
MaxNum int `json:"maxNum,omitempty"`
2127
CmdTimeout int `json:"cmdTimeout,omitempty"`
@@ -94,6 +100,20 @@ func (o *DoOptions) SaveOpts() {
94100
}
95101
}
96102

103+
func (o *DoOptions) SkipPod(podInfo *FloatInfo) bool {
104+
// is check: no skip
105+
if len(o.ResumeRecord) == 0 {
106+
return false
107+
}
108+
// is resume: filt
109+
for _, r := range o.ResumeRecord {
110+
if r.SrcNodeName == podInfo.NodeName {
111+
return false
112+
}
113+
}
114+
return true
115+
}
116+
97117
func (o *DoOptions) Skip(podInfo *FloatInfo, targetIP string) bool {
98118
// is check: no skip
99119
if len(o.ResumeRecord) == 0 {
@@ -112,34 +132,66 @@ func (o *DoOptions) RunRange(iPodInfos []*FloatInfo, jPodInfos []*FloatInfo) []*
112132
var resultData []*PrintCheckData
113133
mutex := sync.Mutex{}
114134

115-
barctl := utils.NewBar(len(jPodInfos) * len(iPodInfos))
135+
var barctl *progressbar.ProgressBar
136+
137+
if len(o.CustomizedTargetIPList) != 0 && len(o.CustomizedTargetPortList) != 0 ||
138+
o.Protocol == string(utils.DNS) {
139+
barctl = utils.NewBar(len(iPodInfos))
140+
} else {
141+
barctl = utils.NewBar(len(jPodInfos) * len(iPodInfos))
142+
}
116143

117144
worker := func(iPodInfo *FloatInfo) {
118-
for _, jPodInfo := range jPodInfos {
119-
for _, ip := range jPodInfo.PodIPs {
120-
var targetIP string
121-
var err error
122-
var cmdResult *command.Result
123-
targetIP = ip
124-
if err != nil {
125-
cmdResult = command.ParseError(err)
126-
} else {
127-
// isSkip
128-
if o.Skip(iPodInfo, targetIP) {
129-
continue
145+
var cmdObj command.Command
146+
if len(o.CustomizedTargetIPList) != 0 && len(o.CustomizedTargetPortList) != 0 {
147+
cmdObj = command.NewCmd(o.Protocol, o.CustomizedTargetIPList, o.CustomizedTargetPortList)
148+
} else if o.Protocol == string(utils.DNS) {
149+
cmdObj = command.NewCmd(o.Protocol, o.TargetHostToLookup, o.TargetDNSServer)
150+
} else {
151+
for _, jPodInfo := range jPodInfos {
152+
for _, ip := range jPodInfo.PodIPs {
153+
var targetIP string
154+
var err error
155+
var cmdResult *command.Result
156+
targetIP = ip
157+
if err != nil {
158+
cmdResult = command.ParseError(err)
159+
} else {
160+
// isSkip
161+
if o.Skip(iPodInfo, targetIP) {
162+
continue
163+
}
164+
// ToDo RunRange && RunNative func support multiple commands, and the code needs to be optimized
165+
cmdObj := command.NewCmd(o.Protocol, targetIP, o.Port)
166+
cmdResult = o.SrcFloater.CommandExec(iPodInfo, cmdObj)
130167
}
131-
// ToDo RunRange && RunNative func support multiple commands, and the code needs to be optimized
132-
cmdObj := command.NewCmd(o.Protocol, targetIP, o.Port)
133-
cmdResult = o.SrcFloater.CommandExec(iPodInfo, cmdObj)
168+
mutex.Lock()
169+
resultData = append(resultData, &PrintCheckData{
170+
*cmdResult,
171+
iPodInfo.NodeName, jPodInfo.NodeName, targetIP,
172+
})
173+
mutex.Unlock()
174+
}
175+
err := barctl.Add(1)
176+
if err != nil {
177+
klog.Error("processs bar event add error")
134178
}
135-
mutex.Lock()
136-
resultData = append(resultData, &PrintCheckData{
137-
*cmdResult,
138-
iPodInfo.NodeName, jPodInfo.NodeName, targetIP,
139-
})
140-
mutex.Unlock()
141179
}
142-
barctl.Add(1)
180+
return
181+
}
182+
if o.SkipPod(iPodInfo) {
183+
return
184+
}
185+
cmdResult := o.SrcFloater.CommandExec(iPodInfo, cmdObj)
186+
mutex.Lock()
187+
resultData = append(resultData, &PrintCheckData{
188+
*cmdResult,
189+
iPodInfo.NodeName, iPodInfo.NodeName, cmdObj.GetTargetStr(),
190+
})
191+
mutex.Unlock()
192+
err := barctl.Add(1)
193+
if err != nil {
194+
klog.Error("processs bar event add error")
143195
}
144196
}
145197

pkg/command/share/floater.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,13 @@ func (f *Floater) CommandExec(fInfo *FloatInfo, cmd command.Command) *command.Re
303303

304304
if err != nil {
305305
// klog.Infof("error: %s", err)
306-
return command.ParseError(fmt.Errorf("%s, stderr: %s", err, errBuffer.String()))
306+
errString := errBuffer.String()
307+
if len(errString) != 0 {
308+
return command.ParseError(fmt.Errorf("%s, stderr: %s", err, errString))
309+
} else {
310+
outString := outBuffer.String()
311+
return command.ParseError(fmt.Errorf("%s, stderr: %s", err, outString))
312+
}
307313
}
308314

309315
return cmd.ParseResult(outBuffer.String())

pkg/command/share/printer.go

+20-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
command "github.com/kosmos.io/netdoctor/pkg/command/share/remote-command"
99
"github.com/kosmos.io/netdoctor/pkg/utils"
1010
"github.com/olekukonko/tablewriter"
11+
"k8s.io/klog/v2"
1112
)
1213

1314
type PrintCheckData struct {
@@ -19,13 +20,13 @@ type PrintCheckData struct {
1920

2021
func PrintResult(resultData []*PrintCheckData) {
2122
table := tablewriter.NewWriter(os.Stdout)
22-
table.SetHeader([]string{"S/N", "SRC_NODE_NAME", "DST_NODE_NAME", "TARGET_IP", "RESULT"})
23+
table.SetHeader([]string{"S/N", "SRC_NODE_NAME", "DST_NODE_NAME", "TARGETP", "RESULT"})
2324

2425
tableException := tablewriter.NewWriter(os.Stdout)
25-
tableException.SetHeader([]string{"S/N", "SRC_NODE_NAME", "DST_NODE_NAME", "TARGET_IP", "RESULT", "LOG"})
26+
tableException.SetHeader([]string{"S/N", "SRC_NODE_NAME", "DST_NODE_NAME", "TARGET", "RESULT", "LOG"})
2627

2728
tableFailed := tablewriter.NewWriter(os.Stdout)
28-
tableFailed.SetHeader([]string{"S/N", "SRC_NODE_NAME", "DST_NODE_NAME", "TARGET_IP", "RESULT", "LOG"})
29+
tableFailed.SetHeader([]string{"S/N", "SRC_NODE_NAME", "DST_NODE_NAME", "TARGET", "RESULT", "LOG"})
2930

3031
resumeData := []*PrintCheckData{}
3132

@@ -61,10 +62,20 @@ func PrintResult(resultData []*PrintCheckData) {
6162
})
6263
}
6364
}
64-
fmt.Println("")
65-
table.Render()
66-
fmt.Println("")
67-
tableException.Render()
68-
69-
utils.WriteResume(resumeData)
65+
if table.NumLines() > 0 {
66+
fmt.Println("")
67+
table.Render()
68+
}
69+
if tableFailed.NumLines() > 0 {
70+
fmt.Println("")
71+
tableFailed.Render()
72+
}
73+
if tableException.NumLines() > 0 {
74+
fmt.Println("")
75+
tableException.Render()
76+
}
77+
err := utils.WriteResume(resumeData)
78+
if err != nil {
79+
klog.Error("write resumeData error")
80+
}
7081
}

pkg/command/share/remote-command/curl.go

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ type Curl struct {
1111
Port string
1212
}
1313

14+
func (c *Curl) GetTargetStr() string {
15+
return fmt.Sprintf("%s:%s", c.TargetIP, c.Port)
16+
}
17+
1418
func (c *Curl) GetCommandStr() string {
1519
// execute once
1620
if utils.IsIPv6(c.TargetIP) {

pkg/command/share/remote-command/interface.go

+23-8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type Result struct {
2020
type Command interface {
2121
GetCommandStr() string
2222
ParseResult(string) *Result
23+
GetTargetStr() string
2324
}
2425

2526
func ParseError(err error) *Result {
@@ -42,15 +43,29 @@ func PrintStatus(status int) string {
4243
return "UNEXCEPTIONED"
4344
}
4445

45-
func NewCmd(protocol string, args ...string) Command {
46-
if protocol == string(utils.TCP) {
47-
return &Curl{
48-
TargetIP: args[0],
49-
Port: args[1],
46+
func NewCmd(protocol string, args ...any) Command {
47+
switch args[1].(type) {
48+
case []string:
49+
return &Ncat{
50+
Protocol: protocol,
51+
TargetIP: args[0].([]string),
52+
Port: args[1].([]string),
5053
}
51-
} else {
52-
return &Ping{
53-
TargetIP: args[0],
54+
default:
55+
if protocol == string(utils.TCP) {
56+
return &Curl{
57+
TargetIP: args[0].(string),
58+
Port: args[1].(string),
59+
}
60+
} else if protocol == string(utils.DNS) {
61+
return &Nslookup{
62+
TargetHost: args[0].(string),
63+
DNSServer: args[1].(string),
64+
}
65+
} else {
66+
return &Ping{
67+
TargetIP: args[0].(string),
68+
}
5469
}
5570
}
5671
}

0 commit comments

Comments
 (0)