Skip to content

Commit

Permalink
Implement list command (#2)
Browse files Browse the repository at this point in the history
* Implement list command

Signed-off-by: Daichi Sakaue <[email protected]>
  • Loading branch information
yokaze authored May 15, 2024
1 parent cbf7e66 commit 321b6a5
Show file tree
Hide file tree
Showing 16 changed files with 844 additions and 135 deletions.
22 changes: 14 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ on:
push:
branches:
- main
env:
cache-version: 1
jobs:
test:
name: e2e
Expand All @@ -16,19 +14,27 @@ jobs:
with:
go-version-file: go.mod
- name: Cache tools
id: cache-tools
uses: actions/cache@v3
with:
path: bin/download
key: cache-${{ env.cache-version }}-go-${{ hashFiles('go.mod') }}-${{ hashFiles('Makefile') }}
key: cache-tools-go-${{ hashFiles('go.mod') }}-${{ hashFiles('Makefile') }}
- name: Cache files
uses: actions/cache@v3
with:
path: cache
key: cache-files-go-${{ hashFiles('go.mod') }}-${{ hashFiles('Makefile') }}
- name: Setup tools
if: steps.cache-tools.outputs.cache-hit != 'true'
run: make setup
- name: Run code check
run: make check-generate
- name: Run lint
run: make lint
- name: Run environment
run: make start
working-directory: e2e
- name: Install
run: make install
run: |
make start
make install-test-pod
make install-policy-viewer
- name: Test
working-directory: e2e
run: make test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@

# Generated files
/bin
/cache
/docs/book
42 changes: 30 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
BIN_DIR := $(shell pwd)/bin
TOOLS_DIR := $(BIN_DIR)/download
CACHE_DIR := $(shell pwd)/cache

HELM_VERSION := 3.14.3
JQ_VERSION := 1.7.1
KIND_VERSION := 0.22.0
Expand All @@ -9,8 +11,10 @@ YQ_VERSION := 4.43.1

# Test tools
CUSTOMCHECKER := $(TOOLS_DIR)/custom-checker
HELM := $(TOOLS_DIR)/helm
HELM_BINARY := $(TOOLS_DIR)/helm
HELM := $(HELM_BINARY) --repository-cache $(CACHE_DIR)/helm/repository --repository-config $(CACHE_DIR)/helm/repositories.yaml
JQ := $(TOOLS_DIR)/jq
KIND := $(TOOLS_DIR)/kind
KUBECTL := $(TOOLS_DIR)/kubectl
KUSTOMIZE := $(TOOLS_DIR)/kustomize
STATICCHECK := $(TOOLS_DIR)/staticcheck
Expand All @@ -26,39 +30,48 @@ help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

.PHONY: setup
setup: $(HELM) $(JQ) $(KUBECTL) $(KUSTOMIZE) $(YQ) ## Install necessary tools
GOBIN=$(TOOLS_DIR) go install sigs.k8s.io/kind@v$(KIND_VERSION)
GOBIN=$(TOOLS_DIR) go install honnef.co/go/tools/cmd/staticcheck@latest
GOBIN=$(TOOLS_DIR) go install github.com/cybozu-go/golang-custom-analyzer/cmd/custom-checker@latest
setup: $(CUSTOMCHECKER) $(HELM_BINARY) $(KIND) $(JQ) $(KUBECTL) $(KUSTOMIZE) $(STATICCHECK) $(YQ) ## Install necessary tools
$(HELM) repo add cilium https://helm.cilium.io/
$(HELM) repo update cilium

$(TOOLS_DIR):
mkdir -p $(TOOLS_DIR)
$(CUSTOMCHECKER):
GOBIN=$(TOOLS_DIR) go install github.com/cybozu-go/golang-custom-analyzer/cmd/custom-checker@latest

$(HELM): $(TOOLS_DIR)
$(HELM_BINARY):
mkdir -p $(TOOLS_DIR)
wget -qO - https://get.helm.sh/helm-v$(HELM_VERSION)-linux-amd64.tar.gz | tar zx -O linux-amd64/helm > $@
chmod +x $@

$(JQ): $(TOOLS_DIR)
$(JQ):
mkdir -p $(TOOLS_DIR)
wget -qO $@ https://github.com/jqlang/jq/releases/download/jq-$(JQ_VERSION)/jq-linux-amd64
chmod +x $@

$(KUBECTL): $(TOOLS_DIR)
$(KIND):
GOBIN=$(TOOLS_DIR) go install sigs.k8s.io/kind@v$(KIND_VERSION)

$(KUBECTL):
mkdir -p $(TOOLS_DIR)
wget -qO $@ https://storage.googleapis.com/kubernetes-release/release/v$(KUBECTL_VERSION)/bin/linux/amd64/kubectl
chmod +x $@

$(KUSTOMIZE): $(TOOLS_DIR)
$(KUSTOMIZE):
mkdir -p $(TOOLS_DIR)
wget -qO - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv$(KUSTOMIZE_VERSION)/kustomize_v$(KUSTOMIZE_VERSION)_linux_amd64.tar.gz | tar zx -O kustomize > $@
chmod +x $@

$(YQ): $(TOOLS_DIR)
$(STATICCHECK):
GOBIN=$(TOOLS_DIR) go install honnef.co/go/tools/cmd/staticcheck@latest

$(YQ):
mkdir -p $(TOOLS_DIR)
wget -qO $@ https://github.com/mikefarah/yq/releases/download/v$(YQ_VERSION)/yq_linux_amd64
chmod +x $@

.PHONY: clean
clean:
rm -rf $(BIN_DIR)
rm -rf $(CACHE_DIR)

##@ Development

Expand All @@ -67,6 +80,11 @@ build: ## Build cilium-policy-viewer
mkdir -p $(BIN_DIR)
go build -o $(BIN_DIR)/cilium-policy main.go

.PHONY: check-generate
check-generate:
go mod tidy
git diff --exit-code --name-only

.PHONY: lint
lint: ## Run lint tools
go vet ./...
Expand Down
59 changes: 10 additions & 49 deletions cmd/dump.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
package cmd

import (
"bytes"
"context"
"errors"
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

var dumpOptions struct {
namespace string
}

func init() {
dumpCmd.Flags().StringVarP(&dumpOptions.namespace, "namespace", "n", "", "namespace of a pod")
rootCmd.AddCommand(dumpCmd)
}

Expand All @@ -37,54 +27,22 @@ var dumpCmd = &cobra.Command{
}

func runDump(ctx context.Context, name string) error {
config, err := rest.InClusterConfig()
clientset, dynamicClient, _, err := createClients(ctx, name)
if err != nil {
return err
}

clientset, _ := kubernetes.NewForConfig(config)
pod, err := clientset.CoreV1().Pods(dumpOptions.namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return err
}
node := pod.Spec.NodeName
proxy, err := clientset.CoreV1().Pods("kube-system").List(ctx, metav1.ListOptions{
FieldSelector: "spec.nodeName=" + node,
LabelSelector: "app.kubernetes.io/name=cilium-agent-proxy",
})
endpointID, err := getPodEndpointID(ctx, dynamicClient, rootOptions.namespace, name)
if err != nil {
return err
}
if len(proxy.Items) != 1 {
return errors.New("proxy not found")
}
proxyIP := proxy.Items[0].Status.PodIP

client, err := dynamic.NewForConfig(config)
proxyEndpoint, err := getProxyEndpoint(ctx, clientset, rootOptions.namespace, name)
if err != nil {
return err
}

gvr := schema.GroupVersionResource{
Group: "cilium.io",
Version: "v2",
Resource: "ciliumendpoints",
}
obj, err := client.Resource(gvr).Namespace(dumpOptions.namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return err
}

endpointID, found, err := unstructured.NestedInt64(obj.Object, "status", "id")
if err != nil {
return err
}
if !found {
return errors.New("endpoint not found")
}

url := fmt.Sprintf("http://%s:8080/v1/endpoint/%d", proxyIP, endpointID)
resp, err := http.Get(url)
resp, err := http.Get(proxyEndpoint + fmt.Sprintf("/v1/endpoint/%d", endpointID))
if err != nil {
return err
}
Expand All @@ -93,6 +51,9 @@ func runDump(ctx context.Context, name string) error {
if err != nil {
return err
}
fmt.Println(string(data))

var buf bytes.Buffer
json.Indent(&buf, data, "", " ")
fmt.Println(buf.String())
return nil
}
91 changes: 91 additions & 0 deletions cmd/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package cmd

import (
"context"
"errors"
"fmt"

"github.com/cilium/cilium/pkg/client"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

func createClients(ctx context.Context, name string) (*kubernetes.Clientset, *dynamic.DynamicClient, *client.Client, error) {
config, err := rest.InClusterConfig()
if err != nil {
return nil, nil, nil, err
}

// Create Kubernetes Clients
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, nil, nil, err
}

dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
return nil, nil, nil, err
}

// Create Cilium Client
endpoint, err := getProxyEndpoint(ctx, clientset, rootOptions.namespace, name)
if err != nil {
return nil, nil, nil, err
}
ciliumClient, err := client.NewClient(endpoint)
if err != nil {
return nil, nil, nil, err
}

return clientset, dynamicClient, ciliumClient, err
}

func getProxyEndpoint(ctx context.Context, c *kubernetes.Clientset, namespace, name string) (string, error) {
targetPod, err := c.CoreV1().Pods(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return "", err
}
targetNode := targetPod.Spec.NodeName

pods, err := c.CoreV1().Pods("kube-system").List(ctx, metav1.ListOptions{
FieldSelector: "spec.nodeName=" + targetNode,
LabelSelector: rootOptions.proxySelector,
})
if err != nil {
return "", err
}
if num := len(pods.Items); num != 1 {
err := fmt.Errorf("failed to find cilium-agent-proxy. found %d pods", num)
return "", err
}

podIP := pods.Items[0].Status.PodIP
return fmt.Sprintf("http://%s:%d", podIP, rootOptions.proxyPort), nil
}

func getPodEndpointID(ctx context.Context, d *dynamic.DynamicClient, namespace, name string) (int64, error) {
gvr := schema.GroupVersionResource{
Group: "cilium.io",
Version: "v2",
Resource: "ciliumendpoints",
}

ep, err := d.Resource(gvr).Namespace(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return 0, err
}

endpointID, found, err := unstructured.NestedInt64(ep.Object, "status", "id")
if err != nil {
return 0, err
}
if !found {
return 0, errors.New("endpoint resource is broken")
}

return endpointID, nil
}
Loading

0 comments on commit 321b6a5

Please sign in to comment.