Skip to content

Commit

Permalink
Add go mod tidy into pre-commit and move nilaway to separate gh job (#…
Browse files Browse the repository at this point in the history
…188)

Signed-off-by: Andrei Kvapil <[email protected]>
  • Loading branch information
hiddenmarten authored and kvaps committed May 20, 2024
1 parent 4b9e67a commit d0b404e
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 7 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/nilaway-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Nilaway lint

on:
pull_request:

jobs:
nilaway-lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/[email protected]
- uses: actions/[email protected]
with:
go-version: 1.22.2
- run: make nilaway-lint
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ repos:
entry: sh -c "make lint-fix"
language: system
require_serial: true
- id: make-nilaway-lint
name: make-nilaway-lint
entry: sh -c "make nilaway-lint"
- id: make-mod-tidy
name: make-mod-tidy
entry: sh -c "make mod-tidy"
language: system
require_serial: true
- id: make-helm-lint
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ fmt: ## Run go fmt against code.
vet: ## Run go vet against code.
go vet ./...

.PHONY: mod-tidy
mod-tidy: ## Run go mod tidy against code.
go mod tidy

.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION_TRIMMED_V) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
Expand Down
229 changes: 229 additions & 0 deletions cmd/plugin/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package main

import (
"context"
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"time"

clientv3 "go.etcd.io/etcd/client/v3"
corev1 "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/tools/portforward"
"k8s.io/client-go/transport/spdy"
"k8s.io/client-go/util/homedir"
)

func main() {
var kubeconfig *string
if home := homedir.HomeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}

namespace := flag.String("namespace", "default", "namespace of the etcd pod")
podName := flag.String("pod", "", "name of the etcd pod")
flag.Parse()

if *podName == "" {
fmt.Println("You must specify the pod name")
return
}

config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
fmt.Printf("Error building kubeconfig: %s\n", err)
return
}

clientset, err := kubernetes.NewForConfig(config)
if err != nil {
fmt.Printf("Error creating Kubernetes client: %s\n", err)
return
}

pod, err := clientset.CoreV1().Pods(*namespace).Get(context.Background(), *podName, metav1.GetOptions{})
if err != nil {
fmt.Printf("Failed to get pod: %s\n", err)
return
}

path := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/portforward", *namespace, *podName)
transport, upgrader, err := spdy.RoundTripperFor(config)
if err != nil {
fmt.Printf("Failed to create round tripper: %s\n", err)
return
}

hostURL, err := url.Parse(config.Host)
if err != nil {
fmt.Printf("Failed to parse host URL: %s\n", err)
return
}

fullPath := *hostURL
fullPath.Path = path

transport, upgrader, err = spdy.RoundTripperFor(config)
if err != nil {
fmt.Printf("Failed to create round tripper: %s\n", err)
return
}

stopChan, readyChan := make(chan struct{}, 1), make(chan struct{}, 1)
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", &fullPath)

portForwarder, err := portforward.New(dialer, []string{"0:2379"}, stopChan, readyChan, os.Stdout, os.Stderr)
if err != nil {
fmt.Printf("Failed to create port forwarder: %s\n", err)
return
}

fmt.Println("Starting port forwarding...")
go func() {
if err := portForwarder.ForwardPorts(); err != nil {
fmt.Printf("Failed to start port forwarding: %s\n", err)
}
}()

<-readyChan // Wait for port forwarding to be ready
fmt.Println("Port forwarding ready")

// Поиск локального порта, использованного для форвардинга
forwardedPorts, err := portForwarder.GetPorts()
if err != nil {
fmt.Printf("Failed to get forwarded ports: %s\n", err)
return
}

localPort := forwardedPorts[0].Local

// Check for the etcd container and extract TLS configuration
tlsConfig, err := getTLSConfig(clientset, pod, *namespace)
if err != nil {
fmt.Printf("Failed to get TLS config: %s\n", err)
return
}

// Connecting to the etcd server with TLS config
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{fmt.Sprintf("localhost:%d", localPort)},
DialTimeout: 5 * time.Second,
TLS: tlsConfig,
})
if err != nil {
fmt.Printf("Failed to connect to etcd server: %s\n", err)
return
}
defer cli.Close()

fmt.Println("Successfully connected to etcd with TLS!")

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
members, err := cli.MemberList(ctx)
if err != nil {
fmt.Printf("Failed to list etcd members: %s\n", err)
return
}

for _, member := range members.Members {
fmt.Printf("ID: %d, Name: %s, PeerURLs: %v, ClientURLs: %v\n",
member.ID, member.Name, member.PeerURLs, member.ClientURLs)
}

// Stop port forwarding
close(stopChan)
fmt.Println("Stopped port forwarding.")
}

func getTLSConfig(clientset *kubernetes.Clientset, pod *corev1.Pod, namespace string) (*tls.Config, error) {
for _, container := range pod.Spec.Containers {
if container.Name == "etcd" {
secretName, err := findSecretNameForTLS(pod, container)
if err != nil {
return nil, err
}

caCertPool, clientCert, err := extractTLSFiles(clientset, namespace, secretName)
if err != nil {
return nil, err
}

return &tls.Config{
Certificates: []tls.Certificate{*clientCert},
RootCAs: caCertPool,
}, nil
}
}
return nil, fmt.Errorf("etcd container not found")
}

func findSecretNameForTLS(pod *corev1.Pod, container corev1.Container) (string, error) {
caFilePath := ""
for _, arg := range append(container.Command, container.Args...) {
if strings.HasPrefix(arg, "--trusted-ca-file=") {
caFilePath = strings.TrimPrefix(arg, "--trusted-ca-file=")
break
}
}

if caFilePath == "" {
return "", fmt.Errorf("trusted CA file path not specified in container args")
}

for _, vm := range container.VolumeMounts {
if strings.HasPrefix(caFilePath, vm.MountPath) {
// We found the mount path, now find the volume
for _, vol := range pod.Spec.Volumes {
if vol.Name == vm.Name && vol.Secret != nil {
return vol.Secret.SecretName, nil
}
}
}
}

return "", fmt.Errorf("secret for the trusted CA file not found")
}

func extractTLSFiles(clientset *kubernetes.Clientset, namespace, secretName string) (*x509.CertPool, *tls.Certificate, error) {
secret, err := clientset.CoreV1().Secrets(namespace).Get(context.Background(), secretName, metav1.GetOptions{})
if err != nil {
return nil, nil, err
}

caPem, ok := secret.Data["ca.crt"]
if !ok {
return nil, nil, fmt.Errorf("CA certificate not found in secret")
}
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caPem) {
return nil, nil, fmt.Errorf("failed to parse CA certificate")
}

certPem, ok := secret.Data["tls.crt"]
if !ok {
return nil, nil, fmt.Errorf("TLS certificate not found in secret")
}
keyPem, ok := secret.Data["tls.key"]
if !ok {
return nil, nil, fmt.Errorf("TLS key not found in secret")
}

clientCert, err := tls.X509KeyPair(certPem, keyPem)
if err != nil {
return nil, nil, fmt.Errorf("failed to create X509 key pair: %s", err)
}

return caCertPool, &clientCert, nil
}
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand Down Expand Up @@ -203,8 +201,6 @@ k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8=
k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
Expand Down

0 comments on commit d0b404e

Please sign in to comment.