From faa73bcf016a0bfb051ad7c3085ff421aae46530 Mon Sep 17 00:00:00 2001 From: daschott Date: Thu, 8 Sep 2022 11:21:20 -0700 Subject: [PATCH 1/2] rename to wcnspect --- .github/ISSUE_TEMPLATE/bug_report.md | 4 +- .github/ISSUE_TEMPLATE/feature_request.md | 4 +- CONTRIBUTING.md | 6 +- Makefile | 12 ++-- README.md | 48 +++++++++------- SUPPORT.md | 4 +- cmd/{winspect => wcnspect}/cmd/capture.go | 14 ++--- cmd/{winspect => wcnspect}/cmd/commands.go | 36 ++++++------ cmd/{winspect => wcnspect}/cmd/counter.go | 10 ++-- cmd/{winspect => wcnspect}/cmd/hns.go | 10 ++-- cmd/{winspect => wcnspect}/cmd/vfpcounter.go | 10 ++-- .../winspect.go => wcnspect/cmd/wcnspect.go} | 4 +- cmd/{winspect => wcnspect}/main.go | 2 +- cmd/{winspectserv => wcnspectserv}/main.go | 6 +- go.mod | 2 +- manifest/Dockerfile | 2 +- ...erv-daemon.yml => wcnspectserv-daemon.yml} | 16 +++--- pkg/client/client.go | 6 +- pkg/client/validate.go | 4 +- pkg/netutil/netutil.go | 2 +- pkg/pkt/pkt.go | 8 +-- pkg/pkt/pkt_test.go | 2 +- pkg/server/server.go | 8 +-- pkg/server/server_test.go | 4 +- pkg/vfputil/vfputil.go | 2 +- rpc/captures.pb.go | 56 +++++++++---------- rpc/captures/captures.proto | 4 +- rpc/captures_grpc.pb.go | 16 +++--- rpc/hcn.pb.go | 14 ++--- rpc/hcn/hcn.proto | 4 +- rpc/hcn_grpc.pb.go | 6 +- 31 files changed, 166 insertions(+), 160 deletions(-) rename cmd/{winspect => wcnspect}/cmd/capture.go (92%) rename cmd/{winspect => wcnspect}/cmd/commands.go (84%) rename cmd/{winspect => wcnspect}/cmd/counter.go (87%) rename cmd/{winspect => wcnspect}/cmd/hns.go (90%) rename cmd/{winspect => wcnspect}/cmd/vfpcounter.go (88%) rename cmd/{winspect/cmd/winspect.go => wcnspect/cmd/wcnspect.go} (70%) rename cmd/{winspect => wcnspect}/main.go (72%) rename cmd/{winspectserv => wcnspectserv}/main.go (89%) rename manifest/{winspectserv-daemon.yml => wcnspectserv-daemon.yml} (73%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index e79d8f9..e80e009 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Create a report to help us improve winspect +about: Create a report to help us improve wcnspect title: '' labels: '' assignees: '' @@ -11,7 +11,7 @@ assignees: '' A clear and concise description of what the bug is. **Component:** -Is the issue in the Winspect Client, the Server, or both? +Is the issue in the wcnspect Client, the Server, or both? **To Reproduce** Steps to reproduce the behavior. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index c79b415..613b09d 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,13 +1,13 @@ --- name: Feature request -about: Suggest an idea for winspect +about: Suggest an idea for wcnspect title: '' labels: '' assignees: '' --- -**Component (Winspect Client or Server):** +**Component (wcnspect Client or Server):** Is this feature request related to the Client or the Server **Is your feature request related to a problem? Please describe.** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ad05120..05941cc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ -# Contribution to Winspect +# Contribution to wcnspect -You can contribute to Winspect with issues and PRs. Simply filing issues for problems you encounter is a great way to contribute. Contributing implementations is also greatly appreciated. +You can contribute to wcnspect with issues and PRs. Simply filing issues for problems you encounter is a great way to contribute. Contributing implementations is also greatly appreciated. ## Reporting Issues -Before filing a new issue, please search our [open issues](https://github.com/microsoft/winspect/issues) to check if it already exists. +Before filing a new issue, please search our [open issues](https://github.com/microsoft/wcnspect/issues) to check if it already exists. If you do find an existing issue, please include your own feedback in the discussion. Do consider upvoting (👍 reaction) the original post, as this helps us prioritize popular issues in our backlog. diff --git a/Makefile b/Makefile index f9a717c..bdd2d1c 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,15 @@ ifeq ($(OS),Windows_NT) - CLIENT_WINDOWS = set `GOARCH=amd64` && set `GOOS=windows` && go build -o out/bin/winspect.exe ./cmd/winspect/ - CLIENT_LINUX = set `GOARCH=amd64` && set `GOOS=linux` && go build -o out/bin/winspect ./cmd/winspect/ + CLIENT_WINDOWS = set `GOARCH=amd64` && set `GOOS=windows` && go build -o out/bin/wcnspect.exe ./cmd/wcnspect/ + CLIENT_LINUX = set `GOARCH=amd64` && set `GOOS=linux` && go build -o out/bin/wcnspect ./cmd/wcnspect/ - SERVER = set `GOARCH=amd64` && set `GOOS=windows` && go build -o out/bin/winspectserv.exe ./cmd/winspectserv/ + SERVER = set `GOARCH=amd64` && set `GOOS=windows` && go build -o out/bin/wcnspectserv.exe ./cmd/wcnspectserv/ CLEAN = rmdir /S /q .\out else - CLIENT_WINDOWS = GOARCH=amd64 GOOS=windows go build -o out/bin/winspect.exe ./cmd/winspect/ - CLIENT_LINUX = GOARCH=amd64 GOOS=linux go build -o out/bin/winspect ./cmd/winspect/ + CLIENT_WINDOWS = GOARCH=amd64 GOOS=windows go build -o out/bin/wcnspect.exe ./cmd/wcnspect/ + CLIENT_LINUX = GOARCH=amd64 GOOS=linux go build -o out/bin/wcnspect ./cmd/wcnspect/ - SERVER = GOARCH=amd64 GOOS=windows go build -o out/bin/winspectserv.exe ./cmd/winspectserv/ + SERVER = GOARCH=amd64 GOOS=windows go build -o out/bin/wcnspectserv.exe ./cmd/wcnspectserv/ CLEAN = rm -rf out endif diff --git a/README.md b/README.md index bb9fbbc..4dc25d7 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Winspect - A Network Diagnostics Tool +# Wcnspect -> A network inspector for the Windows container networking stack on Kubernetes +> **W**indows **c**ontainer **n**etworking **s**tack in**spect**or ## Features -Currently, the winspect tool features four commands - +Currently, the wcnspect tool features four commands - * Capture: runs a packet capture on Windows nodes, Has the capability to filter on pods, IPs, MACs, ports, protocols, and packet type (all, flow, or drop). * Counter: will retrieve packet counter tables from windows nodes. It only outputs a table on nodes currently running a capture. @@ -38,11 +38,11 @@ make server It should be noted that while the client is cross-platform, the server can only run on Windows. -## Winspect Server +## Wcnspect Server -### Deploying the Winspect Server as a DaemonSet (Recommended) +### Deploying the wcnspect Server as a DaemonSet (Recommended) -You can apply the [winspectserv-daemon.yml](manifest/winspectserv-daemon.yml) to deploy the server as a host process container on all Windows nodes. The only way to do this, as of now, is for the user to create their own Azure Container Registry (ACR) and upload the image through there. +You can apply the [wcnspectserv-daemon.yml](manifest/wcnspectserv-daemon.yml) to deploy the server as a host process container on all Windows nodes. The only way to do this, as of now, is for the user to create their own Azure Container Registry (ACR) and upload the image through there. The steps for using ACR are outlined in these docs. The [Dockerfile](manifest/Dockerfile) used for the original image is also contained in [manifest](./manifest). @@ -50,27 +50,27 @@ The [Dockerfile](manifest/Dockerfile) used for the original image is also contai Note that the [manifest](./manifest) directory also contains sample web server deployments for Windows Server 2019 and Windows Server 2022. -### Running Winspect Server directly +### Running wcnspect Server directly If you decide not to deploy the server as a container and manually download it to a node, then it must be run with elevated Administrator permissions. You can run it as follows: > running on the default port of 50051 ```shell -./winspectserv +./wcnspectserv ``` > running on a chosen port of 43058 ```shell -./winspectserv -p 43058 +./wcnspectserv -p 43058 ``` -> **NOTE: The Winspect client only supports connecting to port 50051 currently** +> **NOTE: The wcnspect client only supports connecting to port 50051 currently** -## Winspect Client +## Wcnspect Client The client needs to be executed as a standalone binary from either a Windows or a Linux VM in the same network (jumpbox). -The winspect client reads in the user's `.kube` config file and uses the `default` namespace. +The wcnspect client reads in the user's `.kube` config file and uses the `default` namespace. By default, most commands pull information from *all* Windows nodes. Consequently, when using commands, the user should reference node names and pod names for better filtering of results. @@ -78,9 +78,9 @@ Consequently, when using commands, the user should reference node names and pod > in-depth documentation and examples are available with the -h flag on any command ```shell -winspect -h -winspect capture -h -winspect hns all -h +wcnspect -h +wcnspect capture -h +wcnspect hns all -h ``` For commands that accept lists, input should be comma-separated and without spaces. For example, if we want to capture for 10 seconds on nodes named `win1`, `win2`, and `win3`, while also filtering only for TCP packets, we could do the following: @@ -88,7 +88,7 @@ For commands that accept lists, input should be comma-separated and without spac > sample capture command ```shell -winspect capture nodes win1,win2,win3 -t TCP -d 10 +wcnspect capture nodes win1,win2,win3 -t TCP -d 10 ``` The command will be routed to each node's internal IP on the cluster. It should be noted that if we don't pass a duration, the command will run indefinitely. Additionally, we can terminate the process on the referenced nodes at any time with `Ctrl+C`. @@ -98,22 +98,28 @@ Note that if we pass the `--counters-only` flag to the `capture` command, then p > sample capture command using --counters-only ```shell -winspect capture nodes win1 --counters-only +wcnspect capture nodes win1 --counters-only ``` Importantly, while the `vfp-counter` command runs on its own (given a pod), the `counter` command is tied to running instances of the `capture` command. Consequently, in order for it to output a table on any given node, a capture must be run on that node at the same time. The table will output packet counts tied to that capture. ```shell -winspect capture nodes win1,win3 -t TCP -winspect counter +wcnspect capture nodes win1,win3 -t TCP +wcnspect counter ``` ## Assumptions Currently, this project's code makes the following assumptions: -* The port that winspect server nodes use is 50051 (this is currently required on the client-side). -* When applying `winspectserv-daemon.yml`, the user has access to the ACR referenced in the file. +* The port that wcnspect server uses is 50051 (this is currently required on the client-side). +* When applying `wcnspectserv-daemon.yml`, the user has access to the ACR referenced in the file. + +## TODO + * Read in `$KUBECONFIG` env var. + * Support for other ports on client side. + * Namespace support for pods. + ## Contributing diff --git a/SUPPORT.md b/SUPPORT.md index c91a717..250ab4a 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,9 +2,9 @@ ## How to file issues and get help -This project uses GitHub Issues to track bugs and feature requests. Please search the [open issues](https://github.com/microsoft/winspect/issues) before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a [new issue](https://github.com/microsoft/winspect/issues/new). +This project uses GitHub Issues to track bugs and feature requests. Please search the [open issues](https://github.com/microsoft/wcnspect/issues) before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a [new issue](https://github.com/microsoft/wcnspect/issues/new). -The Winspect project maintainers will respond to the best of their abilities on a best effort basis. +The wcnspect project maintainers will respond to the best of their abilities on a best effort basis. For help and questions about using this project, please reach out to @daschott on the [#sig-windows](https://kubernetes.slack.com/messages/sig-windows) channel. diff --git a/cmd/winspect/cmd/capture.go b/cmd/wcnspect/cmd/capture.go similarity index 92% rename from cmd/winspect/cmd/capture.go rename to cmd/wcnspect/cmd/capture.go index f4b602c..ce27bc3 100644 --- a/cmd/winspect/cmd/capture.go +++ b/cmd/wcnspect/cmd/capture.go @@ -11,9 +11,9 @@ import ( "sync" "syscall" - "github.com/microsoft/winspect/pkg/client" - "github.com/microsoft/winspect/pkg/k8spi" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/client" + "github.com/microsoft/wcnspect/pkg/k8spi" + pb "github.com/microsoft/wcnspect/rpc" "github.com/spf13/cobra" ) @@ -39,13 +39,13 @@ func (b *commandsBuilder) newCaptureCmd() *captureCmd { Use: "capture", Short: "The 'capture' command will run a packet capture on all windows nodes.", Long: `The 'capture' command will run a packet capture on all windows nodes. For example: - 'winspect capture pods {pods} --protocols TCP -d 10'.`, + 'wcnspect capture pods {pods} --protocols TCP -d 10'.`, } captureTypes := []string{"all", "nodes", "pods"} captureHelp := map[string]string{ "all": "Runs on all windows nodes in the AKS cluster.", - "nodes": "Specify which nodes winspect should send requests to using node names.", + "nodes": "Specify which nodes wcnspect should send requests to using node names.", "pods": "Specify which pods the capture should filter on. Supports up to two pod names. Automatically defines nodes to capture on.", } for _, name := range captureTypes { @@ -85,7 +85,7 @@ func (cc *captureCmd) printCapture(subcmd string, endpoints []string) { switch subcmd { case "nodes": if len(endpoints) == 0 { - log.Fatal("must pass node names when using 'winspect capture nodes ...'") + log.Fatal("must pass node names when using 'wcnspect capture nodes ...'") } nodes := strings.Split(endpoints[0], ",") @@ -96,7 +96,7 @@ func (cc *captureCmd) printCapture(subcmd string, endpoints []string) { targetNodes = cc.getNodes(nodes) case "pods": if len(endpoints) == 0 { - log.Fatal("must pass pod names when using 'winspect capture pods ...'") + log.Fatal("must pass pod names when using 'wcnspect capture pods ...'") } pods := strings.Split(endpoints[0], ",") diff --git a/cmd/winspect/cmd/commands.go b/cmd/wcnspect/cmd/commands.go similarity index 84% rename from cmd/winspect/cmd/commands.go rename to cmd/wcnspect/cmd/commands.go index a31e840..5f5bbc3 100644 --- a/cmd/winspect/cmd/commands.go +++ b/cmd/wcnspect/cmd/commands.go @@ -9,8 +9,8 @@ import ( "log" "path/filepath" - "github.com/microsoft/winspect/common" - "github.com/microsoft/winspect/pkg/comprise" + "github.com/microsoft/wcnspect/common" + "github.com/microsoft/wcnspect/pkg/comprise" "github.com/spf13/cobra" v1 "k8s.io/api/core/v1" @@ -21,7 +21,7 @@ import ( ) type commandsBuilder struct { - winspectBuilderCommon + wcnspectBuilderCommon commands []cmder } @@ -50,8 +50,8 @@ func (b *commandsBuilder) addAll() *commandsBuilder { return b } -func (b *commandsBuilder) build() *winspectCmd { - h := b.newWinspectCmd() +func (b *commandsBuilder) build() *wcnspectCmd { + h := b.newwcnspectCmd() addCommands(h.getCommand(), b.commands...) return h } @@ -81,16 +81,16 @@ func (b *commandsBuilder) newBuilderCmd(cmd *cobra.Command) *baseBuilderCmd { return bcmd } -type winspectCmd struct { +type wcnspectCmd struct { *baseBuilderCmd } -func (b *commandsBuilder) newWinspectCmd() *winspectCmd { - cc := &winspectCmd{} +func (b *commandsBuilder) newwcnspectCmd() *wcnspectCmd { + cc := &wcnspectCmd{} cc.baseBuilderCmd = b.newBuilderCmd(&cobra.Command{ - Use: "winspect", - Short: "Winspect is an advanced distributed packet capture and HNS log collection tool.", + Use: "wcnspect", + Short: "wcnspect is an advanced distributed packet capture and HNS log collection tool.", Long: `An advanced distributed packet capture and HNS log collection tool made with Go (^_^)`, }) @@ -108,7 +108,7 @@ func (b *commandsBuilder) newWinspectCmd() *winspectCmd { return cc } -type winspectBuilderCommon struct { +type wcnspectBuilderCommon struct { kubeconfig string winNodeNames map[string]v1.Node // node name -> v1.Node @@ -117,7 +117,7 @@ type winspectBuilderCommon struct { podsNode map[string]v1.Node // pod name -> v1.Node (pod's node) } -func (cc *winspectBuilderCommon) initializeAKSClusterValues() { +func (cc *wcnspectBuilderCommon) initializeAKSClusterValues() { // Use the current context in kubeconfig config, err := clientcmd.BuildConfigFromFlags("", cc.kubeconfig) if err != nil { @@ -167,7 +167,7 @@ func (cc *winspectBuilderCommon) initializeAKSClusterValues() { } } -func (cc *winspectBuilderCommon) getNodes(nodeNames []string) (ret []v1.Node) { +func (cc *wcnspectBuilderCommon) getNodes(nodeNames []string) (ret []v1.Node) { for _, name := range nodeNames { ret = append(ret, cc.winNodeNames[name]) } @@ -177,7 +177,7 @@ func (cc *winspectBuilderCommon) getNodes(nodeNames []string) (ret []v1.Node) { /* Takes a list of pod names. Creates a map with these pods and returns it. Returns a map of node names to a list of pod ips. */ -func (cc *winspectBuilderCommon) getNodePodMap(podNames []string) map[string][]string { +func (cc *wcnspectBuilderCommon) getNodePodMap(podNames []string) map[string][]string { ret := make(map[string][]string) for _, podName := range podNames { @@ -195,23 +195,23 @@ func (cc *winspectBuilderCommon) getNodePodMap(podNames []string) map[string][]s /* Returns a list of the nodes associated with the passed pod names. */ -func (cc *winspectBuilderCommon) getPodsNodes(podNames []string) (ret []v1.Node) { +func (cc *wcnspectBuilderCommon) getPodsNodes(podNames []string) (ret []v1.Node) { for _, name := range podNames { ret = append(ret, cc.podsNode[name]) } return } -func (cc *winspectBuilderCommon) getPodNames() []string { +func (cc *wcnspectBuilderCommon) getPodNames() []string { return comprise.Keys(cc.podNames) } -func (cc *winspectBuilderCommon) getWinNodes() []v1.Node { +func (cc *wcnspectBuilderCommon) getWinNodes() []v1.Node { //FIXME: the below line should be commented out if not testing on local // return []v1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "localhost"}, Status: v1.NodeStatus{Addresses: []v1.NodeAddress{{Type: "InternalIP", Address: "0.0.0.0"}}}}} return comprise.Values(cc.winNodeNames) } -func (cc *winspectBuilderCommon) getWinNodeNames() []string { +func (cc *wcnspectBuilderCommon) getWinNodeNames() []string { return comprise.Keys(cc.winNodeNames) } diff --git a/cmd/winspect/cmd/counter.go b/cmd/wcnspect/cmd/counter.go similarity index 87% rename from cmd/winspect/cmd/counter.go rename to cmd/wcnspect/cmd/counter.go index 994d742..ebe9fef 100644 --- a/cmd/winspect/cmd/counter.go +++ b/cmd/wcnspect/cmd/counter.go @@ -7,9 +7,9 @@ import ( "log" "sync" - "github.com/microsoft/winspect/pkg/client" - "github.com/microsoft/winspect/pkg/k8spi" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/client" + "github.com/microsoft/wcnspect/pkg/k8spi" + pb "github.com/microsoft/wcnspect/rpc" "github.com/spf13/cobra" ) @@ -29,13 +29,13 @@ func (b *commandsBuilder) newCounterCmd() *counterCmd { Short: "The 'counter' command will retrieve packet counter tables from all windows nodes.", Long: `The 'counter' command will retrieve packet counter tables from all windows nodes. This command requires that a capture is being run on the requested nodes. For example: - 'winspect counter --nodes {nodes} --include-hidden`, + 'wcnspect counter --nodes {nodes} --include-hidden`, Run: func(cmd *cobra.Command, args []string) { cc.printCounters() }, } - cmd.PersistentFlags().StringSliceVarP(&cc.nodes, "nodes", "n", []string{}, "Specify which nodes winspect should send requests to using node names. Runs on all windows nodes by default.") + cmd.PersistentFlags().StringSliceVarP(&cc.nodes, "nodes", "n", []string{}, "Specify which nodes wcnspect should send requests to using node names. Runs on all windows nodes by default.") cmd.PersistentFlags().BoolVarP(&cc.includeHidden, "include-hidden", "i", false, "Show counters from components that are hidden by default.") cc.baseBuilderCmd = b.newBuilderCmd(cmd) diff --git a/cmd/winspect/cmd/hns.go b/cmd/wcnspect/cmd/hns.go similarity index 90% rename from cmd/winspect/cmd/hns.go rename to cmd/wcnspect/cmd/hns.go index 4a8a971..338a056 100644 --- a/cmd/winspect/cmd/hns.go +++ b/cmd/wcnspect/cmd/hns.go @@ -7,9 +7,9 @@ import ( "log" "sync" - "github.com/microsoft/winspect/pkg/client" - "github.com/microsoft/winspect/pkg/k8spi" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/client" + "github.com/microsoft/wcnspect/pkg/k8spi" + pb "github.com/microsoft/wcnspect/rpc" "github.com/spf13/cobra" ) @@ -28,7 +28,7 @@ func (b *commandsBuilder) newHnsCmd() *hnsCmd { Use: "hns", Short: "The 'hns' command will retrieve hns logs on all windows nodes.", Long: `The 'hns' command will retrieve hns logs on all windows nodes. For example: - 'winspect hns all --nodes {nodes} --json`, + 'wcnspect hns all --nodes {nodes} --json`, } logTypes := []string{"all", "endpoints", "loadbalancers", "namespaces", "networks"} @@ -51,7 +51,7 @@ func (b *commandsBuilder) newHnsCmd() *hnsCmd { cmd.AddCommand(subcmd) } - cmd.PersistentFlags().StringSliceVarP(&cc.nodes, "nodes", "n", []string{}, "Specify which nodes winspect should send requests to using node names. Runs on all windows nodes by default.") + cmd.PersistentFlags().StringSliceVarP(&cc.nodes, "nodes", "n", []string{}, "Specify which nodes wcnspect should send requests to using node names. Runs on all windows nodes by default.") cmd.PersistentFlags().BoolVarP(&cc.verbose, "json", "d", false, "Detailed option for logs.") cc.baseBuilderCmd = b.newBuilderCmd(cmd) diff --git a/cmd/winspect/cmd/vfpcounter.go b/cmd/wcnspect/cmd/vfpcounter.go similarity index 88% rename from cmd/winspect/cmd/vfpcounter.go rename to cmd/wcnspect/cmd/vfpcounter.go index 2c4e5ab..2b41bc5 100644 --- a/cmd/winspect/cmd/vfpcounter.go +++ b/cmd/wcnspect/cmd/vfpcounter.go @@ -7,9 +7,9 @@ import ( "log" "sync" - "github.com/microsoft/winspect/pkg/client" - "github.com/microsoft/winspect/pkg/k8spi" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/client" + "github.com/microsoft/wcnspect/pkg/k8spi" + pb "github.com/microsoft/wcnspect/rpc" "github.com/spf13/cobra" ) @@ -29,13 +29,13 @@ func (b *commandsBuilder) newVfpCounterCmd() *vfpCounterCmd { Short: "The 'vfp-counter' command will retrieve packet counter tables from a specified windows pod's port VFP.", Long: `The 'vfp-counter' command will retrieve packet counter tables from a specified windows pod's port VFP. For example: - 'winspect vfp-counter --pod {pod}'`, + 'wcnspect vfp-counter --pod {pod}'`, Run: func(cmd *cobra.Command, args []string) { cc.printVFPCounters() }, } - cmd.PersistentFlags().StringVarP(&cc.pod, "pod", "p", "", "Specify which pod winspect should send requests to using pod name. This flag is required.") + cmd.PersistentFlags().StringVarP(&cc.pod, "pod", "p", "", "Specify which pod wcnspect should send requests to using pod name. This flag is required.") cmd.PersistentFlags().BoolVarP(&cc.verbose, "detailed", "d", false, "Option to output Host vNic and External Adapter Port counters.") cmd.MarkPersistentFlagRequired("pod") diff --git a/cmd/winspect/cmd/winspect.go b/cmd/wcnspect/cmd/wcnspect.go similarity index 70% rename from cmd/winspect/cmd/winspect.go rename to cmd/wcnspect/cmd/wcnspect.go index 283c85b..8e9ae2f 100644 --- a/cmd/winspect/cmd/winspect.go +++ b/cmd/wcnspect/cmd/wcnspect.go @@ -9,8 +9,8 @@ import ( ) func Execute() { - winspectCmd := newCommandsBuilder().addAll().build() - cmd := winspectCmd.getCommand() + wcnspectCmd := newCommandsBuilder().addAll().build() + cmd := wcnspectCmd.getCommand() if err := cmd.Execute(); err != nil { fmt.Println(err) diff --git a/cmd/winspect/main.go b/cmd/wcnspect/main.go similarity index 72% rename from cmd/winspect/main.go rename to cmd/wcnspect/main.go index 692309f..3c846fc 100644 --- a/cmd/winspect/main.go +++ b/cmd/wcnspect/main.go @@ -4,7 +4,7 @@ package main import ( - "github.com/microsoft/winspect/cmd/winspect/cmd" + "github.com/microsoft/wcnspect/cmd/wcnspect/cmd" ) func main() { diff --git a/cmd/winspectserv/main.go b/cmd/wcnspectserv/main.go similarity index 89% rename from cmd/winspectserv/main.go rename to cmd/wcnspectserv/main.go index 578d5e8..c343624 100644 --- a/cmd/winspectserv/main.go +++ b/cmd/wcnspectserv/main.go @@ -9,9 +9,9 @@ import ( "net" "strconv" - "github.com/microsoft/winspect/common" - "github.com/microsoft/winspect/pkg/server" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/common" + "github.com/microsoft/wcnspect/pkg/server" + pb "github.com/microsoft/wcnspect/rpc" flag "github.com/spf13/pflag" "google.golang.org/grpc" diff --git a/go.mod b/go.mod index 4eb6ed5..fa71a9b 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/microsoft/winspect +module github.com/microsoft/wcnspect go 1.18 diff --git a/manifest/Dockerfile b/manifest/Dockerfile index 418fae3..9ce3b16 100644 --- a/manifest/Dockerfile +++ b/manifest/Dockerfile @@ -3,4 +3,4 @@ FROM mcr.microsoft.com/oss/kubernetes/windows-host-process-containers-base-image ENV PATH="C:\Windows\system32;C:\Windows;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;" WORKDIR /app -ADD ./winspectserv.exe /app +ADD ./wcnspectserv.exe /app diff --git a/manifest/winspectserv-daemon.yml b/manifest/wcnspectserv-daemon.yml similarity index 73% rename from manifest/winspectserv-daemon.yml rename to manifest/wcnspectserv-daemon.yml index 701b86f..73d1915 100644 --- a/manifest/winspectserv-daemon.yml +++ b/manifest/wcnspectserv-daemon.yml @@ -2,18 +2,18 @@ apiVersion: apps/v1 kind: DaemonSet metadata: labels: - app: winspect-server - name: winspect-server + app: wcnspect-server + name: wcnspect-server namespace: kube-system spec: selector: matchLabels: - app: winspect-server + app: wcnspect-server template: metadata: labels: - app: winspect-server - name: winspect-server + app: wcnspect-server + name: wcnspect-server namespace: kube-system spec: tolerations: @@ -30,12 +30,12 @@ spec: runAsNonRoot: false hostNetwork: true containers: - - name: windowswinspectserver - image: nikosacr.azurecr.io/winspect:latest + - name: windowswcnspectserver + image: nikosacr.azurecr.io/wcnspect:latest command: - powershell.exe - -command - - ./winspectserv.exe # can add `-p {num}` here to change server's port + - ./wcnspectserv.exe # can add `-p {num}` here to change server's port securityContext: privileged: true nodeSelector: diff --git a/pkg/client/client.go b/pkg/client/client.go index c7d5440..fd57a93 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -10,9 +10,9 @@ import ( "log" "sync" - "github.com/microsoft/winspect/common" - "github.com/microsoft/winspect/pkg/k8spi" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/common" + "github.com/microsoft/wcnspect/pkg/k8spi" + pb "github.com/microsoft/wcnspect/rpc" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" diff --git a/pkg/client/validate.go b/pkg/client/validate.go index e3c62bb..4ce88b4 100644 --- a/pkg/client/validate.go +++ b/pkg/client/validate.go @@ -9,8 +9,8 @@ import ( "strconv" "strings" - "github.com/microsoft/winspect/common" - "github.com/microsoft/winspect/pkg/comprise" + "github.com/microsoft/wcnspect/common" + "github.com/microsoft/wcnspect/pkg/comprise" ) var validTCPFormats = comprise.Map(strings.Split(common.ValidTCPFlags, " "), func(s string) string { return "TCP_" + s }) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index c4cff75..a6325b6 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -53,7 +53,7 @@ func GetLogs(option string, verbose bool) ([]byte, error) { cmd := fmt.Sprintf("hnsdiag list %s", option) if verbose { - cmd += " -d" + cmd += " -dl" } return exec.Command("cmd", "/c", cmd).CombinedOutput() diff --git a/pkg/pkt/pkt.go b/pkg/pkt/pkt.go index afb9798..f2fa535 100644 --- a/pkg/pkt/pkt.go +++ b/pkg/pkt/pkt.go @@ -11,9 +11,9 @@ import ( "os/exec" "strings" - "github.com/microsoft/winspect/pkg/comprise" - "github.com/microsoft/winspect/pkg/netutil" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/comprise" + "github.com/microsoft/wcnspect/pkg/netutil" + pb "github.com/microsoft/wcnspect/rpc" ) var pktParams = map[string]string{ @@ -41,7 +41,7 @@ func AddFilters(filters *pb.Filters) error { pktProtocols := comprise.Map(protocols, formatTCPFlags) for i, protocol := range protocols { - name := "winspect" + strings.ToUpper(protocol) + name := "wcnspect" + strings.ToUpper(protocol) filterBuilder := []string{} // Build filter slice diff --git a/pkg/pkt/pkt_test.go b/pkg/pkt/pkt_test.go index 4fc7ed5..b7b4191 100644 --- a/pkg/pkt/pkt_test.go +++ b/pkg/pkt/pkt_test.go @@ -6,7 +6,7 @@ package pkt import ( "testing" - pb "github.com/microsoft/winspect/rpc" + pb "github.com/microsoft/wcnspect/rpc" ) func TestAddFilters(t *testing.T) { diff --git a/pkg/server/server.go b/pkg/server/server.go index ac4f836..329a720 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -11,10 +11,10 @@ import ( "os/exec" "time" - "github.com/microsoft/winspect/pkg/netutil" - "github.com/microsoft/winspect/pkg/pkt" - "github.com/microsoft/winspect/pkg/vfputil" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/netutil" + "github.com/microsoft/wcnspect/pkg/pkt" + "github.com/microsoft/wcnspect/pkg/vfputil" + pb "github.com/microsoft/wcnspect/rpc" "google.golang.org/protobuf/types/known/timestamppb" ) diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 697d055..9698c88 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -9,8 +9,8 @@ import ( "net" "testing" - "github.com/microsoft/winspect/pkg/netutil" - pb "github.com/microsoft/winspect/rpc" + "github.com/microsoft/wcnspect/pkg/netutil" + pb "github.com/microsoft/wcnspect/rpc" "google.golang.org/grpc" "google.golang.org/grpc/test/bufconn" diff --git a/pkg/vfputil/vfputil.go b/pkg/vfputil/vfputil.go index d47eb82..9fc430c 100644 --- a/pkg/vfputil/vfputil.go +++ b/pkg/vfputil/vfputil.go @@ -9,7 +9,7 @@ import ( "regexp" "strings" - "github.com/microsoft/winspect/pkg/netutil" + "github.com/microsoft/wcnspect/pkg/netutil" ) type VFPPort struct { diff --git a/rpc/captures.pb.go b/rpc/captures.pb.go index 7950452..aed3bc9 100644 --- a/rpc/captures.pb.go +++ b/rpc/captures.pb.go @@ -148,7 +148,7 @@ type Modifiers struct { unknownFields protoimpl.UnknownFields Pods []string `protobuf:"bytes,1,rep,name=pods,proto3" json:"pods,omitempty"` - PacketType PacketType `protobuf:"varint,4,opt,name=packet_type,json=packetType,proto3,enum=winspect.captures.PacketType" json:"packet_type,omitempty"` + PacketType PacketType `protobuf:"varint,4,opt,name=packet_type,json=packetType,proto3,enum=wcnspect.captures.PacketType" json:"packet_type,omitempty"` CountersOnly bool `protobuf:"varint,5,opt,name=counters_only,json=countersOnly,proto3" json:"counters_only,omitempty"` } @@ -754,36 +754,36 @@ func file_captures_proto_rawDescGZIP() []byte { var file_captures_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_captures_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_captures_proto_goTypes = []interface{}{ - (PacketType)(0), // 0: winspect.captures.PacketType - (*Filters)(nil), // 1: winspect.captures.Filters - (*Modifiers)(nil), // 2: winspect.captures.Modifiers - (*Empty)(nil), // 3: winspect.captures.Empty - (*CaptureRequest)(nil), // 4: winspect.captures.CaptureRequest - (*CountersRequest)(nil), // 5: winspect.captures.CountersRequest - (*VFPCountersRequest)(nil), // 6: winspect.captures.VFPCountersRequest - (*CaptureResponse)(nil), // 7: winspect.captures.CaptureResponse - (*StopCaptureResponse)(nil), // 8: winspect.captures.StopCaptureResponse - (*CountersResponse)(nil), // 9: winspect.captures.CountersResponse - (*VFPCountersResponse)(nil), // 10: winspect.captures.VFPCountersResponse + (PacketType)(0), // 0: wcnspect.captures.PacketType + (*Filters)(nil), // 1: wcnspect.captures.Filters + (*Modifiers)(nil), // 2: wcnspect.captures.Modifiers + (*Empty)(nil), // 3: wcnspect.captures.Empty + (*CaptureRequest)(nil), // 4: wcnspect.captures.CaptureRequest + (*CountersRequest)(nil), // 5: wcnspect.captures.CountersRequest + (*VFPCountersRequest)(nil), // 6: wcnspect.captures.VFPCountersRequest + (*CaptureResponse)(nil), // 7: wcnspect.captures.CaptureResponse + (*StopCaptureResponse)(nil), // 8: wcnspect.captures.StopCaptureResponse + (*CountersResponse)(nil), // 9: wcnspect.captures.CountersResponse + (*VFPCountersResponse)(nil), // 10: wcnspect.captures.VFPCountersResponse (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp } var file_captures_proto_depIdxs = []int32{ - 0, // 0: winspect.captures.Modifiers.packet_type:type_name -> winspect.captures.PacketType - 11, // 1: winspect.captures.CaptureRequest.timestamp:type_name -> google.protobuf.Timestamp - 2, // 2: winspect.captures.CaptureRequest.modifier:type_name -> winspect.captures.Modifiers - 1, // 3: winspect.captures.CaptureRequest.filter:type_name -> winspect.captures.Filters - 11, // 4: winspect.captures.CaptureResponse.timestamp:type_name -> google.protobuf.Timestamp - 11, // 5: winspect.captures.StopCaptureResponse.timestamp:type_name -> google.protobuf.Timestamp - 11, // 6: winspect.captures.CountersResponse.timestamp:type_name -> google.protobuf.Timestamp - 11, // 7: winspect.captures.VFPCountersResponse.timestamp:type_name -> google.protobuf.Timestamp - 4, // 8: winspect.captures.CaptureService.StartCapture:input_type -> winspect.captures.CaptureRequest - 3, // 9: winspect.captures.CaptureService.StopCapture:input_type -> winspect.captures.Empty - 5, // 10: winspect.captures.CaptureService.GetCounters:input_type -> winspect.captures.CountersRequest - 6, // 11: winspect.captures.CaptureService.GetVFPCounters:input_type -> winspect.captures.VFPCountersRequest - 7, // 12: winspect.captures.CaptureService.StartCapture:output_type -> winspect.captures.CaptureResponse - 8, // 13: winspect.captures.CaptureService.StopCapture:output_type -> winspect.captures.StopCaptureResponse - 9, // 14: winspect.captures.CaptureService.GetCounters:output_type -> winspect.captures.CountersResponse - 10, // 15: winspect.captures.CaptureService.GetVFPCounters:output_type -> winspect.captures.VFPCountersResponse + 0, // 0: wcnspect.captures.Modifiers.packet_type:type_name -> wcnspect.captures.PacketType + 11, // 1: wcnspect.captures.CaptureRequest.timestamp:type_name -> google.protobuf.Timestamp + 2, // 2: wcnspect.captures.CaptureRequest.modifier:type_name -> wcnspect.captures.Modifiers + 1, // 3: wcnspect.captures.CaptureRequest.filter:type_name -> wcnspect.captures.Filters + 11, // 4: wcnspect.captures.CaptureResponse.timestamp:type_name -> google.protobuf.Timestamp + 11, // 5: wcnspect.captures.StopCaptureResponse.timestamp:type_name -> google.protobuf.Timestamp + 11, // 6: wcnspect.captures.CountersResponse.timestamp:type_name -> google.protobuf.Timestamp + 11, // 7: wcnspect.captures.VFPCountersResponse.timestamp:type_name -> google.protobuf.Timestamp + 4, // 8: wcnspect.captures.CaptureService.StartCapture:input_type -> wcnspect.captures.CaptureRequest + 3, // 9: wcnspect.captures.CaptureService.StopCapture:input_type -> wcnspect.captures.Empty + 5, // 10: wcnspect.captures.CaptureService.GetCounters:input_type -> wcnspect.captures.CountersRequest + 6, // 11: wcnspect.captures.CaptureService.GetVFPCounters:input_type -> wcnspect.captures.VFPCountersRequest + 7, // 12: wcnspect.captures.CaptureService.StartCapture:output_type -> wcnspect.captures.CaptureResponse + 8, // 13: wcnspect.captures.CaptureService.StopCapture:output_type -> wcnspect.captures.StopCaptureResponse + 9, // 14: wcnspect.captures.CaptureService.GetCounters:output_type -> wcnspect.captures.CountersResponse + 10, // 15: wcnspect.captures.CaptureService.GetVFPCounters:output_type -> wcnspect.captures.VFPCountersResponse 12, // [12:16] is the sub-list for method output_type 8, // [8:12] is the sub-list for method input_type 8, // [8:8] is the sub-list for extension type_name diff --git a/rpc/captures/captures.proto b/rpc/captures/captures.proto index be6ec39..3ff174d 100644 --- a/rpc/captures/captures.proto +++ b/rpc/captures/captures.proto @@ -2,8 +2,8 @@ // Licensed under the MIT license. syntax = "proto3"; -option go_package = "github.com/microsoft/winspect/rpc"; -package winspect.captures; +option go_package = "github.com/microsoft/wcnspect/rpc"; +package wcnspect.captures; import "google/protobuf/timestamp.proto"; diff --git a/rpc/captures_grpc.pb.go b/rpc/captures_grpc.pb.go index e0ac773..2be1904 100644 --- a/rpc/captures_grpc.pb.go +++ b/rpc/captures_grpc.pb.go @@ -33,7 +33,7 @@ func NewCaptureServiceClient(cc grpc.ClientConnInterface) CaptureServiceClient { } func (c *captureServiceClient) StartCapture(ctx context.Context, in *CaptureRequest, opts ...grpc.CallOption) (CaptureService_StartCaptureClient, error) { - stream, err := c.cc.NewStream(ctx, &CaptureService_ServiceDesc.Streams[0], "/winspect.captures.CaptureService/StartCapture", opts...) + stream, err := c.cc.NewStream(ctx, &CaptureService_ServiceDesc.Streams[0], "/wcnspect.captures.CaptureService/StartCapture", opts...) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func (x *captureServiceStartCaptureClient) Recv() (*CaptureResponse, error) { func (c *captureServiceClient) StopCapture(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StopCaptureResponse, error) { out := new(StopCaptureResponse) - err := c.cc.Invoke(ctx, "/winspect.captures.CaptureService/StopCapture", in, out, opts...) + err := c.cc.Invoke(ctx, "/wcnspect.captures.CaptureService/StopCapture", in, out, opts...) if err != nil { return nil, err } @@ -75,7 +75,7 @@ func (c *captureServiceClient) StopCapture(ctx context.Context, in *Empty, opts func (c *captureServiceClient) GetCounters(ctx context.Context, in *CountersRequest, opts ...grpc.CallOption) (*CountersResponse, error) { out := new(CountersResponse) - err := c.cc.Invoke(ctx, "/winspect.captures.CaptureService/GetCounters", in, out, opts...) + err := c.cc.Invoke(ctx, "/wcnspect.captures.CaptureService/GetCounters", in, out, opts...) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (c *captureServiceClient) GetCounters(ctx context.Context, in *CountersRequ func (c *captureServiceClient) GetVFPCounters(ctx context.Context, in *VFPCountersRequest, opts ...grpc.CallOption) (*VFPCountersResponse, error) { out := new(VFPCountersResponse) - err := c.cc.Invoke(ctx, "/winspect.captures.CaptureService/GetVFPCounters", in, out, opts...) + err := c.cc.Invoke(ctx, "/wcnspect.captures.CaptureService/GetVFPCounters", in, out, opts...) if err != nil { return nil, err } @@ -162,7 +162,7 @@ func _CaptureService_StopCapture_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/winspect.captures.CaptureService/StopCapture", + FullMethod: "/wcnspect.captures.CaptureService/StopCapture", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(CaptureServiceServer).StopCapture(ctx, req.(*Empty)) @@ -180,7 +180,7 @@ func _CaptureService_GetCounters_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/winspect.captures.CaptureService/GetCounters", + FullMethod: "/wcnspect.captures.CaptureService/GetCounters", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(CaptureServiceServer).GetCounters(ctx, req.(*CountersRequest)) @@ -198,7 +198,7 @@ func _CaptureService_GetVFPCounters_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/winspect.captures.CaptureService/GetVFPCounters", + FullMethod: "/wcnspect.captures.CaptureService/GetVFPCounters", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(CaptureServiceServer).GetVFPCounters(ctx, req.(*VFPCountersRequest)) @@ -210,7 +210,7 @@ func _CaptureService_GetVFPCounters_Handler(srv interface{}, ctx context.Context // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var CaptureService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "winspect.captures.CaptureService", + ServiceName: "wcnspect.captures.CaptureService", HandlerType: (*CaptureServiceServer)(nil), Methods: []grpc.MethodDesc{ { diff --git a/rpc/hcn.pb.go b/rpc/hcn.pb.go index 96419b1..9e93dc7 100644 --- a/rpc/hcn.pb.go +++ b/rpc/hcn.pb.go @@ -81,7 +81,7 @@ type HCNRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Hcntype HCNType `protobuf:"varint,1,opt,name=hcntype,proto3,enum=winspect.hcn.HCNType" json:"hcntype,omitempty"` + Hcntype HCNType `protobuf:"varint,1,opt,name=hcntype,proto3,enum=wcnspect.hcn.HCNType" json:"hcntype,omitempty"` Verbose bool `protobuf:"varint,2,opt,name=verbose,proto3" json:"verbose,omitempty"` } @@ -223,14 +223,14 @@ func file_hcn_proto_rawDescGZIP() []byte { var file_hcn_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_hcn_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_hcn_proto_goTypes = []interface{}{ - (HCNType)(0), // 0: winspect.hcn.HCNType - (*HCNRequest)(nil), // 1: winspect.hcn.HCNRequest - (*HCNResponse)(nil), // 2: winspect.hcn.HCNResponse + (HCNType)(0), // 0: wcnspect.hcn.HCNType + (*HCNRequest)(nil), // 1: wcnspect.hcn.HCNRequest + (*HCNResponse)(nil), // 2: wcnspect.hcn.HCNResponse } var file_hcn_proto_depIdxs = []int32{ - 0, // 0: winspect.hcn.HCNRequest.hcntype:type_name -> winspect.hcn.HCNType - 1, // 1: winspect.hcn.HCNService.GetHCNLogs:input_type -> winspect.hcn.HCNRequest - 2, // 2: winspect.hcn.HCNService.GetHCNLogs:output_type -> winspect.hcn.HCNResponse + 0, // 0: wcnspect.hcn.HCNRequest.hcntype:type_name -> wcnspect.hcn.HCNType + 1, // 1: wcnspect.hcn.HCNService.GetHCNLogs:input_type -> wcnspect.hcn.HCNRequest + 2, // 2: wcnspect.hcn.HCNService.GetHCNLogs:output_type -> wcnspect.hcn.HCNResponse 2, // [2:3] is the sub-list for method output_type 1, // [1:2] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name diff --git a/rpc/hcn/hcn.proto b/rpc/hcn/hcn.proto index 8becf85..969d681 100644 --- a/rpc/hcn/hcn.proto +++ b/rpc/hcn/hcn.proto @@ -2,8 +2,8 @@ // Licensed under the MIT license. syntax = "proto3"; -option go_package = "github.com/microsoft/winspect/rpc"; -package winspect.hcn; +option go_package = "github.com/microsoft/wcnspect/rpc"; +package wcnspect.hcn; // models enum HCNType { diff --git a/rpc/hcn_grpc.pb.go b/rpc/hcn_grpc.pb.go index 14622e5..3f8e546 100644 --- a/rpc/hcn_grpc.pb.go +++ b/rpc/hcn_grpc.pb.go @@ -31,7 +31,7 @@ func NewHCNServiceClient(cc grpc.ClientConnInterface) HCNServiceClient { func (c *hCNServiceClient) GetHCNLogs(ctx context.Context, in *HCNRequest, opts ...grpc.CallOption) (*HCNResponse, error) { out := new(HCNResponse) - err := c.cc.Invoke(ctx, "/winspect.hcn.HCNService/GetHCNLogs", in, out, opts...) + err := c.cc.Invoke(ctx, "/wcnspect.hcn.HCNService/GetHCNLogs", in, out, opts...) if err != nil { return nil, err } @@ -76,7 +76,7 @@ func _HCNService_GetHCNLogs_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/winspect.hcn.HCNService/GetHCNLogs", + FullMethod: "/wcnspect.hcn.HCNService/GetHCNLogs", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(HCNServiceServer).GetHCNLogs(ctx, req.(*HCNRequest)) @@ -88,7 +88,7 @@ func _HCNService_GetHCNLogs_Handler(srv interface{}, ctx context.Context, dec fu // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var HCNService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "winspect.hcn.HCNService", + ServiceName: "wcnspect.hcn.HCNService", HandlerType: (*HCNServiceServer)(nil), Methods: []grpc.MethodDesc{ { From 9557d3af85bba12bdcf1c167c42dc22b3de15f1e Mon Sep 17 00:00:00 2001 From: daschott Date: Mon, 12 Sep 2022 14:34:16 -0700 Subject: [PATCH 2/2] Added namespace support to pod commands --- README.md | 8 +- cmd/wcnspect/cmd/capture.go | 44 ++++++---- cmd/wcnspect/cmd/commands.go | 90 +++----------------- cmd/wcnspect/cmd/counter.go | 4 +- cmd/wcnspect/cmd/hns.go | 4 +- cmd/wcnspect/cmd/vfpcounter.go | 70 +++++++-------- cmd/wcnspect/cmd/wcnspect.go | 4 + common/constants.go | 3 +- pkg/client/client.go | 4 +- pkg/k8sapi/k8sapi.go | 150 +++++++++++++++++++++++++++++++++ pkg/k8spi/k8spi.go | 86 ------------------- 11 files changed, 242 insertions(+), 225 deletions(-) create mode 100644 pkg/k8sapi/k8sapi.go delete mode 100644 pkg/k8spi/k8spi.go diff --git a/README.md b/README.md index 4dc25d7..4860f2d 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,9 @@ If you decide not to deploy the server as a container and manually download it t ## Wcnspect Client The client needs to be executed as a standalone binary from either a Windows or a Linux VM in the same network (jumpbox). -The wcnspect client reads in the user's `.kube` config file and uses the `default` namespace. +The wcnspect client requires access to the [Kubernetes cluster config](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/). + +By default, Wcnspect client will search for a file named `config` in the `$HOME/.kube` directory. Otherwise, it will use the $KUBECONFIG environment variable. By default, most commands pull information from *all* Windows nodes. Consequently, when using commands, the user should reference node names and pod names for better filtering of results. @@ -116,9 +118,7 @@ Currently, this project's code makes the following assumptions: * When applying `wcnspectserv-daemon.yml`, the user has access to the ACR referenced in the file. ## TODO - * Read in `$KUBECONFIG` env var. - * Support for other ports on client side. - * Namespace support for pods. + * Support for other ports on the Wcnspect client. ## Contributing diff --git a/cmd/wcnspect/cmd/capture.go b/cmd/wcnspect/cmd/capture.go index ce27bc3..1020973 100644 --- a/cmd/wcnspect/cmd/capture.go +++ b/cmd/wcnspect/cmd/capture.go @@ -11,9 +11,11 @@ import ( "sync" "syscall" + "github.com/microsoft/wcnspect/common" "github.com/microsoft/wcnspect/pkg/client" - "github.com/microsoft/wcnspect/pkg/k8spi" + "github.com/microsoft/wcnspect/pkg/k8sapi" pb "github.com/microsoft/wcnspect/rpc" + v1 "k8s.io/api/core/v1" "github.com/spf13/cobra" ) @@ -28,6 +30,7 @@ type captureCmd struct { packetType string countersOnly bool + namespace string *baseBuilderCmd } @@ -39,14 +42,14 @@ func (b *commandsBuilder) newCaptureCmd() *captureCmd { Use: "capture", Short: "The 'capture' command will run a packet capture on all windows nodes.", Long: `The 'capture' command will run a packet capture on all windows nodes. For example: - 'wcnspect capture pods {pods} --protocols TCP -d 10'.`, + 'wcnspect capture pods {pod1,pod2} --protocols TCP -d 10'.`, } captureTypes := []string{"all", "nodes", "pods"} captureHelp := map[string]string{ "all": "Runs on all windows nodes in the AKS cluster.", - "nodes": "Specify which nodes wcnspect should send requests to using node names.", - "pods": "Specify which pods the capture should filter on. Supports up to two pod names. Automatically defines nodes to capture on.", + "nodes": "Specify which nodes wcnspect should send requests to using comma-separated node names.", + "pods": "Specify which pods the capture should filter on. Supports up to two comma-separated pod names.", } for _, name := range captureTypes { subcmd := &cobra.Command{ @@ -56,10 +59,8 @@ func (b *commandsBuilder) newCaptureCmd() *captureCmd { cc.printCapture(cmd.Name(), args) }, } - cmd.AddCommand(subcmd) } - cmd.PersistentFlags().Int32VarP(&cc.time, "time", "d", 0, "Time to run packet capture for (in seconds). Runs indefinitely given 0.") cmd.PersistentFlags().StringSliceVarP(&cc.ips, "ips", "i", []string{}, "Match source or destination IP address. CIDR supported.") @@ -69,7 +70,7 @@ func (b *commandsBuilder) newCaptureCmd() *captureCmd { cmd.PersistentFlags().StringVar(&cc.packetType, "type", "all", "Select which packets to capture. Can be all, flow, or drop.") cmd.PersistentFlags().BoolVar(&cc.countersOnly, "counters-only", false, "Collect packet counters only. No packet logging.") - + cmd.PersistentFlags().StringVarP(&cc.namespace, "namespace", "n", common.DefaultNamespace, "Specify Kubernetes namespace to filter pods on.") cc.baseBuilderCmd = b.newBuilderCmd(cmd) return cc @@ -77,12 +78,14 @@ func (b *commandsBuilder) newCaptureCmd() *captureCmd { func (cc *captureCmd) printCapture(subcmd string, endpoints []string) { cc.validateArgs() - - targetNodes := cc.getWinNodes() + var targetNodes []v1.Node + // Store mapping of NodeName => Pod IPs hostMap := make(map[string][]string) // Revise nodes and pods arguments based on command name switch subcmd { + default: + targetNodes = cc.getWinNodes() case "nodes": if len(endpoints) == 0 { log.Fatal("must pass node names when using 'wcnspect capture nodes ...'") @@ -92,20 +95,29 @@ func (cc *captureCmd) printCapture(subcmd string, endpoints []string) { if err := client.ValidateNodes(nodes, cc.getWinNodeNames()); err != nil { log.Fatal(err) } - targetNodes = cc.getNodes(nodes) case "pods": + // Use namespace command + //cc.cmd.PersistentFlags().StringVar(&cc.namespace, "namespace", common.DefaultNamespace, "Optionally specify Kubernetes namespace to filter pods on.") if len(endpoints) == 0 { log.Fatal("must pass pod names when using 'wcnspect capture pods ...'") } pods := strings.Split(endpoints[0], ",") - if err := client.ValidatePods(pods, cc.getPodNames()); err != nil { - log.Fatal(err) + // Namespace + ns := k8sclient.GetNamespace(cc.namespace) + // Loop over Pod, Node + var p *v1.Pod + var nodeName string + for _, podName := range pods { + p = k8sclient.GetPod(podName, ns.GetName()) + nodeName = p.Spec.NodeName + podIP := p.Status.PodIP + if nodeName != "" { + hostMap[nodeName] = append(hostMap[nodeName], podIP) + targetNodes = append(targetNodes, cc.getNode(nodeName)) + } } - - hostMap = cc.getNodePodMap(pods) - targetNodes = cc.getPodsNodes(pods) } // Capture any sigint to send a StopCapture request @@ -121,7 +133,7 @@ func (cc *captureCmd) printCapture(subcmd string, endpoints []string) { for _, node := range targetNodes { wg.Add(1) - name, ip := node.GetName(), k8spi.RetrieveInternalIP(node) + name, ip := node.GetName(), k8sapi.RetrieveInternalIP(node) c, closeClient := client.CreateConnection(ip) defer closeClient() diff --git a/cmd/wcnspect/cmd/commands.go b/cmd/wcnspect/cmd/commands.go index 5f5bbc3..736c350 100644 --- a/cmd/wcnspect/cmd/commands.go +++ b/cmd/wcnspect/cmd/commands.go @@ -4,20 +4,14 @@ package cmd import ( - "context" "fmt" "log" - "path/filepath" - "github.com/microsoft/wcnspect/common" "github.com/microsoft/wcnspect/pkg/comprise" + "github.com/microsoft/wcnspect/pkg/k8sapi" "github.com/spf13/cobra" v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/util/homedir" ) type commandsBuilder struct { @@ -93,16 +87,8 @@ func (b *commandsBuilder) newwcnspectCmd() *wcnspectCmd { Short: "wcnspect is an advanced distributed packet capture and HNS log collection tool.", Long: `An advanced distributed packet capture and HNS log collection tool made with Go (^_^)`, }) - - if home := homedir.HomeDir(); home != "" { - cc.cmd.PersistentFlags().StringVar(&cc.kubeconfig, "kubeconfig", filepath.Join(home, ".kube", "config"), "Optionally specify absolute path to the kubeconfig file.") - } else { - cc.cmd.PersistentFlags().StringVar(&cc.kubeconfig, "kubeconfig", "", "Specify absolute path to the kubeconfig file.") - cc.cmd.MarkPersistentFlagRequired("kubeconfig") - } - + cc.cmd.PersistentFlags().StringVar(&cc.kubeconfig, "kubeconfig", "", "Specify absolute path to the kubeconfig file.") cc.cmd.CompletionOptions.DisableDefaultCmd = true - cc.initializeAKSClusterValues() return cc @@ -112,58 +98,27 @@ type wcnspectBuilderCommon struct { kubeconfig string winNodeNames map[string]v1.Node // node name -> v1.Node - podNames map[string]v1.Pod // pod name -> v1.Pod - - podsNode map[string]v1.Node // pod name -> v1.Node (pod's node) } func (cc *wcnspectBuilderCommon) initializeAKSClusterValues() { - // Use the current context in kubeconfig - config, err := clientcmd.BuildConfigFromFlags("", cc.kubeconfig) - if err != nil { - log.Fatal(err) - } - - // Create the clientset - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - log.Fatal(err) - } + k8sclient = k8sapi.New(cc.kubeconfig) // Pull windows nodes - nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: "kubernetes.io/os=windows"}) - if err != nil { - log.Fatal(err) - } + nodes := k8sclient.GetAllNodesWindows() // Pull pods while creating mapping of node : pods cc.winNodeNames = make(map[string]v1.Node) - cc.podNames = make(map[string]v1.Pod) - cc.podsNode = make(map[string]v1.Node) + for _, node := range nodes.Items { nodeName := node.GetName() // Set node names to node items cc.winNodeNames[nodeName] = node - - // Pull pods - filter := fmt.Sprintf("spec.nodeName=%s", nodeName) - pods, err := clientset.CoreV1().Pods(common.Namespace).List(context.TODO(), metav1.ListOptions{FieldSelector: filter}) - if err != nil { - log.Fatal(err) - } - - // Set pods' names to node - for _, pod := range pods.Items { - podName := pod.GetName() - cc.podsNode[podName] = node - cc.podNames[podName] = pod - } } // Validate there is at least one windows node if len(cc.winNodeNames) == 0 { - log.Fatal("no windows nodes exist") + log.Fatal("no Windows nodes exist") } } @@ -174,38 +129,15 @@ func (cc *wcnspectBuilderCommon) getNodes(nodeNames []string) (ret []v1.Node) { return } -/* Takes a list of pod names. Creates a map with these pods and returns it. -Returns a map of node names to a list of pod ips. -*/ -func (cc *wcnspectBuilderCommon) getNodePodMap(podNames []string) map[string][]string { - ret := make(map[string][]string) - - for _, podName := range podNames { - node := cc.podsNode[podName] - - nodeName := node.GetName() - if nodeName != "" { - ret[nodeName] = append(ret[nodeName], cc.podNames[podName].Status.PodIP) - } - } - - return ret -} - -/* -Returns a list of the nodes associated with the passed pod names. -*/ -func (cc *wcnspectBuilderCommon) getPodsNodes(podNames []string) (ret []v1.Node) { - for _, name := range podNames { - ret = append(ret, cc.podsNode[name]) +func (cc *wcnspectBuilderCommon) getNode(nodeName string) (node v1.Node) { + if n, ok := cc.winNodeNames[nodeName]; ok { + node = n + } else { + log.Fatalf(fmt.Sprintf("Windows node %s not found", nodeName)) } return } -func (cc *wcnspectBuilderCommon) getPodNames() []string { - return comprise.Keys(cc.podNames) -} - func (cc *wcnspectBuilderCommon) getWinNodes() []v1.Node { //FIXME: the below line should be commented out if not testing on local // return []v1.Node{{ObjectMeta: metav1.ObjectMeta{Name: "localhost"}, Status: v1.NodeStatus{Addresses: []v1.NodeAddress{{Type: "InternalIP", Address: "0.0.0.0"}}}}} diff --git a/cmd/wcnspect/cmd/counter.go b/cmd/wcnspect/cmd/counter.go index ebe9fef..f94a02f 100644 --- a/cmd/wcnspect/cmd/counter.go +++ b/cmd/wcnspect/cmd/counter.go @@ -8,7 +8,7 @@ import ( "sync" "github.com/microsoft/wcnspect/pkg/client" - "github.com/microsoft/wcnspect/pkg/k8spi" + "github.com/microsoft/wcnspect/pkg/k8sapi" pb "github.com/microsoft/wcnspect/rpc" "github.com/spf13/cobra" @@ -58,7 +58,7 @@ func (cc *counterCmd) printCounters() { for _, node := range targetNodes { wg.Add(1) - name, ip := node.GetName(), k8spi.RetrieveInternalIP(node) + name, ip := node.GetName(), k8sapi.RetrieveInternalIP(node) c, closeClient := client.CreateConnection(ip) defer closeClient() diff --git a/cmd/wcnspect/cmd/hns.go b/cmd/wcnspect/cmd/hns.go index 338a056..745bd56 100644 --- a/cmd/wcnspect/cmd/hns.go +++ b/cmd/wcnspect/cmd/hns.go @@ -8,7 +8,7 @@ import ( "sync" "github.com/microsoft/wcnspect/pkg/client" - "github.com/microsoft/wcnspect/pkg/k8spi" + "github.com/microsoft/wcnspect/pkg/k8sapi" pb "github.com/microsoft/wcnspect/rpc" "github.com/spf13/cobra" @@ -74,7 +74,7 @@ func (cc *hnsCmd) printLogs(subcmd string) { for _, node := range targetNodes { wg.Add(1) - name, ip := node.GetName(), k8spi.RetrieveInternalIP(node) + name, ip := node.GetName(), k8sapi.RetrieveInternalIP(node) c, closeClient := client.CreateConnection(ip) defer closeClient() diff --git a/cmd/wcnspect/cmd/vfpcounter.go b/cmd/wcnspect/cmd/vfpcounter.go index 2b41bc5..9bedd5a 100644 --- a/cmd/wcnspect/cmd/vfpcounter.go +++ b/cmd/wcnspect/cmd/vfpcounter.go @@ -4,19 +4,21 @@ package cmd import ( - "log" "sync" + "github.com/microsoft/wcnspect/common" "github.com/microsoft/wcnspect/pkg/client" - "github.com/microsoft/wcnspect/pkg/k8spi" + "github.com/microsoft/wcnspect/pkg/k8sapi" pb "github.com/microsoft/wcnspect/rpc" + v1 "k8s.io/api/core/v1" "github.com/spf13/cobra" ) type vfpCounterCmd struct { - pod string - verbose bool + pod string + verbose bool + namespace string *baseBuilderCmd } @@ -37,6 +39,7 @@ func (b *commandsBuilder) newVfpCounterCmd() *vfpCounterCmd { cmd.PersistentFlags().StringVarP(&cc.pod, "pod", "p", "", "Specify which pod wcnspect should send requests to using pod name. This flag is required.") cmd.PersistentFlags().BoolVarP(&cc.verbose, "detailed", "d", false, "Option to output Host vNic and External Adapter Port counters.") + cmd.PersistentFlags().StringVar(&cc.namespace, "namespace", common.DefaultNamespace, "Optionally specify Kubernetes namespace to filter pods on.") cmd.MarkPersistentFlagRequired("pod") cc.baseBuilderCmd = b.newBuilderCmd(cmd) @@ -45,39 +48,40 @@ func (b *commandsBuilder) newVfpCounterCmd() *vfpCounterCmd { } func (cc *vfpCounterCmd) printVFPCounters() { + // Read in pods pods := []string{cc.pod} - - if err := client.ValidatePods(pods, cc.getPodNames()); err != nil { - log.Fatal(err) - } - - hostMap := cc.getNodePodMap(pods) - targetNodes := cc.getPodsNodes(pods) - + // Namespace + ns := k8sclient.GetNamespace(cc.namespace) + // Loop over Pod, Node + var p *v1.Pod + var nodeName string var wg sync.WaitGroup - for _, node := range targetNodes { - wg.Add(1) - - name, ip := node.GetName(), k8spi.RetrieveInternalIP(node) - c, closeClient := client.CreateConnection(ip) - defer closeClient() - - ctx := &client.ReqContext{ - Server: client.Node{ - Name: name, - Ip: ip, - }, - Wg: &wg, - } - - req := &pb.VFPCountersRequest{ - Pod: hostMap[name][0], - Verbose: cc.verbose, + for _, podName := range pods { + p = k8sclient.GetPod(podName, ns.GetName()) + nodeName = p.Spec.NodeName + podIP := p.Status.PodIP + if nodeName != "" { + wg.Add(1) + nodeIP := k8sapi.RetrieveInternalIP(cc.getNode(nodeName)) + c, closeClient := client.CreateConnection(nodeIP) + defer closeClient() + + ctx := &client.ReqContext{ + Server: client.Node{ + Name: nodeName, + Ip: nodeIP, + }, + Wg: &wg, + } + + req := &pb.VFPCountersRequest{ + Pod: podIP, + Verbose: cc.verbose, + } + + go client.PrintVFPCounters(c, req, ctx) } - - go client.PrintVFPCounters(c, req, ctx) } - wg.Wait() } diff --git a/cmd/wcnspect/cmd/wcnspect.go b/cmd/wcnspect/cmd/wcnspect.go index 8e9ae2f..976c81d 100644 --- a/cmd/wcnspect/cmd/wcnspect.go +++ b/cmd/wcnspect/cmd/wcnspect.go @@ -6,8 +6,12 @@ package cmd import ( "fmt" "os" + + "github.com/microsoft/wcnspect/pkg/k8sapi" ) +var k8sclient k8sapi.K8sapi + func Execute() { wcnspectCmd := newCommandsBuilder().addAll().build() cmd := wcnspectCmd.getCommand() diff --git a/common/constants.go b/common/constants.go index acf6be7..20bd838 100644 --- a/common/constants.go +++ b/common/constants.go @@ -5,7 +5,8 @@ package common const ( DefaultServerPort = "50051" - Namespace = "default" + DefaultNamespace = "default" + KubeConfigEnvVar = "KUBECONFIG" ValidProtocols = "TCP UDP ICMP ICMPv6" ValidTCPFlags = "FIN SYN RST PSH ACK URG ECE CWR" ValidPacketTypes = "ALL FLOW DROP" diff --git a/pkg/client/client.go b/pkg/client/client.go index fd57a93..748c34d 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -11,7 +11,7 @@ import ( "sync" "github.com/microsoft/wcnspect/common" - "github.com/microsoft/wcnspect/pkg/k8spi" + "github.com/microsoft/wcnspect/pkg/k8sapi" pb "github.com/microsoft/wcnspect/rpc" "google.golang.org/grpc" @@ -160,7 +160,7 @@ func Cleanup(nodes []v1.Node) { wg.Add(1) // Get target name and ip - name, ip := node.GetName(), k8spi.RetrieveInternalIP(node) + name, ip := node.GetName(), k8sapi.RetrieveInternalIP(node) // Create connections c, closeClient := CreateConnection(ip) diff --git a/pkg/k8sapi/k8sapi.go b/pkg/k8sapi/k8sapi.go new file mode 100644 index 0000000..2630b35 --- /dev/null +++ b/pkg/k8sapi/k8sapi.go @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package k8sapi + +import ( + "context" + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/microsoft/wcnspect/common" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/util/homedir" +) + +// K8sapi is used to request data from the Kubernetes API-Server +type K8sapi struct { + config *rest.Config + conn *kubernetes.Clientset +} + +// Constructor for K8sapi +func New(config string) K8sapi { + if config == "" { + // $HOME/.kube/config + home := homedir.HomeDir() + filename := filepath.Join(home, ".kube", "config") + + // Check KUBECONFIG environment var + if conf, ok := os.LookupEnv(common.KubeConfigEnvVar); ok && len(conf) != 0 { + config = filepath.Clean(conf) + // Check $HOME/.kube/config + } else if _, err := ioutil.ReadFile(filename); err == nil { + config = filename + } else { + log.Fatal("Error reading $KUBECONFIG environment variable. Exiting...") + } + } + // Use the current context in kubeconfig + kubeconfig, err := clientcmd.BuildConfigFromFlags("", config) + if err != nil { + log.Fatalln("Error reading kubeconfig: ", err) + } + // Create the clientset + clientset, err := kubernetes.NewForConfig(kubeconfig) + if err != nil { + log.Fatalln("Error reading kubeconfig: ", err) + } + return K8sapi{kubeconfig, clientset} +} + +func (k8sclient *K8sapi) GetPod(podName string, kubenamespace string) *v1.Pod { + pod, err := k8sclient.conn.CoreV1().Pods(kubenamespace).Get(context.TODO(), podName, metav1.GetOptions{}) + if err != nil { + log.Fatal(err) + } + return pod +} + +func (k8sclient *K8sapi) GetNode(nodeName string) *v1.Node { + node, err := k8sclient.conn.CoreV1().Nodes().Get(context.TODO(), nodeName, metav1.GetOptions{}) + if err != nil { + log.Fatal(err) + } + return node +} + +func (k8sclient *K8sapi) GetAllNodesWindows() *v1.NodeList { + nodes, err := k8sclient.conn.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: "kubernetes.io/os=windows"}) + if err != nil { + log.Fatal(err) + } + return nodes +} + +func (k8sclient *K8sapi) GetNamespace(namespace string) *v1.Namespace { + ns, err := k8sclient.conn.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) + if err != nil { + log.Fatal(err) + } + return ns +} + +// Operations on v1.Node objects +func FilterNodes(nodes []v1.Node, test func(v1.Node) bool) (ret []v1.Node) { + for _, node := range nodes { + if test(node) { + ret = append(ret, node) + } + } + return + +} + +/* Retrieves node names and ips given a list of nodes +return map of node name to node ip +*/ +func GetNodesNameToIp(nodes []v1.Node) map[string]string { + ret := map[string]string{} + for _, node := range nodes { + ret[node.GetName()] = RetrieveInternalIP(node) + } + + return ret +} + +func GetNodesIpToName(nodes []v1.Node) map[string]string { + ret := map[string]string{} + for _, node := range nodes { + ret[RetrieveInternalIP(node)] = node.GetName() + } + + return ret +} + +func MapNodes(nodes []v1.Node, f func(v1.Node) string) (ret []string) { + for _, node := range nodes { + ret = append(ret, f(node)) + } + return +} + +func MapNodeNames(nodes []string, f func(string) v1.Node) (ret []v1.Node) { + for _, node := range nodes { + ret = append(ret, f(node)) + } + return +} + +func RetrieveInternalIP(node v1.Node) string { + for _, addr := range node.Status.Addresses { + if addr.Type == "InternalIP" { + return addr.Address + } + } + + return "" +} + +func WindowsOS(node v1.Node) bool { + return node.GetLabels()["kubernetes.io/os"] == "windows" +} + +/* Pod Methods */ diff --git a/pkg/k8spi/k8spi.go b/pkg/k8spi/k8spi.go deleted file mode 100644 index ce9f2ae..0000000 --- a/pkg/k8spi/k8spi.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -package k8spi - -import ( - v1 "k8s.io/api/core/v1" -) - -// Node Methods -func FilterNodes(nodes []v1.Node, test func(v1.Node) bool) (ret []v1.Node) { - for _, node := range nodes { - if test(node) { - ret = append(ret, node) - } - } - return -} - -/* Retrieves node names and ips given a list of nodes -return map of node name to node ip -*/ -func GetNodesNameToIp(nodes []v1.Node) map[string]string { - ret := map[string]string{} - for _, node := range nodes { - ret[node.GetName()] = RetrieveInternalIP(node) - } - - return ret -} - -func GetNodesIpToName(nodes []v1.Node) map[string]string { - ret := map[string]string{} - for _, node := range nodes { - ret[RetrieveInternalIP(node)] = node.GetName() - } - - return ret -} - -func MapNodes(nodes []v1.Node, f func(v1.Node) string) (ret []string) { - for _, node := range nodes { - ret = append(ret, f(node)) - } - return -} - -func MapNodeNames(nodes []string, f func(string) v1.Node) (ret []v1.Node) { - for _, node := range nodes { - ret = append(ret, f(node)) - } - return -} - -func RetrieveInternalIP(node v1.Node) string { - for _, addr := range node.Status.Addresses { - if addr.Type == "InternalIP" { - return addr.Address - } - } - - return "" -} - -func WindowsOS(node v1.Node) bool { - return node.GetLabels()["kubernetes.io/os"] == "windows" -} - -// Pod Methods -func GetPodMaps(pods []v1.Pod) (map[string]string, map[string]string) { - ips := map[string]string{} - nodes := map[string]string{} - for _, pod := range pods { - ips[pod.GetName()] = pod.Status.PodIP - nodes[pod.GetName()] = pod.Status.HostIP - } - - return ips, nodes -} - -func MapPods(pods []v1.Pod, f func(v1.Pod) string) (ret []string) { - for _, pod := range pods { - ret = append(ret, f(pod)) - } - return -}