Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: Add inCluster related API and xenon checker #596

Merged
merged 2 commits into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions build/xenon/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM golang:1.16 as builder

WORKDIR /
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go env -w GOPROXY=https://goproxy.cn,direct;
#     go mod download
RUN  go mod download

# Copy the go source
COPY cmd/xenon/main.go cmd/xenon/main.go
COPY utils/ utils/

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o bin/xenonchecker cmd/xenon/main.go

FROM radondb/xenon:1.1.5-alpha

COPY --from=builder /bin/xenonchecker /xenonchecker
1 change: 1 addition & 0 deletions cmd/staticcheck.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
checks=[ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-ST1001"]
88 changes: 88 additions & 0 deletions cmd/xenon/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package main

import (
"log"
"os"

. "github.com/radondb/radondb-mysql-kubernetes/utils"
)

var (
ns string
podName string
)

func init() {
ns = os.Getenv("NAMESPACE")
podName = os.Getenv("POD_NAME")
}

func main() {
switch os.Args[1] {
case "leaderStart":
if err := leaderStart(); err != nil {
log.Fatalf("leaderStart failed: %v", err)
}
case "leaderStop":
if err := leaderStop(); err != nil {
log.Fatalf("leaderStop failed: %v", err)
}
case "liveness":
if err := liveness(); err != nil {
log.Fatalf("liveness failed: %v", err)
}
case "readiness":
if err := readiness(); err != nil {
log.Fatalf("readiness failed: %v", err)
}
case "postStart":
if err := postStart(); err != nil {
log.Fatalf("postStart failed: %v", err)
}
case "preStop":
if err := preStop(); err != nil {
log.Fatalf("postStop failed: %v", err)
}
default:
log.Fatalf("Usage: %s leaderStart|leaderStop|liveness|readiness|postStart|preStop", os.Args[0])
}
}

// TODO
func leaderStart() error {
return nil
}

func leaderStop() error {
return PatchRoleLabelTo(myself(string(Follower)))
}

func liveness() error {
return XenonPingMyself()
}

func readiness() error {
role := GetRole()
if role != string(Leader) {
return PatchRoleLabelTo(myself(role))
}
return nil
}

// TODO
func postStart() error {
return nil
}

// TODO
func preStop() error {
return nil
}

func myself(role string) MySQLNode {
return MySQLNode{
PodName: podName,
Namespace: ns,
Role: role,
}
}
21 changes: 20 additions & 1 deletion mysqlcluster/container/xenon.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,26 @@ func (c *xenon) getCommand() []string {

// getEnvVars get the container env.
func (c *xenon) getEnvVars() []corev1.EnvVar {
return nil
return []corev1.EnvVar{
{
Name: "NameSpace",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.namespace",
},
},
},
{
Name: "POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
},
},
}
}

// getLifecycle get the container lifecycle.
Expand Down
21 changes: 20 additions & 1 deletion mysqlcluster/container/xenon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,26 @@ func TestGetXenonCommand(t *testing.T) {
}

func TestGetXenonEnvVar(t *testing.T) {
assert.Nil(t, xenonCase.Env)
assert.Equal(t, []corev1.EnvVar{
{
Name: "NameSpace",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.namespace",
},
},
},
{
Name: "POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
},
},
}, xenonCase.Env)
}

func TestGetXenonLifecycle(t *testing.T) {
Expand Down
81 changes: 81 additions & 0 deletions utils/incluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package utils

import (
"context"
"encoding/json"
"fmt"
"log"
"os/exec"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

type raftStatus struct {
Leader string `json:"leader"`
State string `json:"state"`
Nodes []string `json:"nodes"`
}

type MySQLNode struct {
PodName string
Namespace string
Role string
}

func GetClientSet() (*kubernetes.Clientset, error) {
// Creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
return nil, fmt.Errorf("failed to create in-cluster config: %v", err)
}
// Creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to create clientset: %v", err)
}
return clientset, nil
}

func PatchRoleLabelTo(n MySQLNode) error {
// Creates the clientset
clientset, err := GetClientSet()
if err != nil {
return fmt.Errorf("failed to create clientset: %v", err)
}
patch := fmt.Sprintf(`{"metadata":{"labels":{"role":"%s"}}}`, n.Role)
_, err = clientset.CoreV1().Pods(n.Namespace).Patch(context.TODO(), n.PodName, types.MergePatchType, []byte(patch), metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("failed to patch pod role label: %v", err)
}
return nil
}

func XenonPingMyself() error {
args := []string{"xenon", "ping"}
cmd := exec.Command("xenoncli", args...)
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to exec xenoncli xenon ping: %v", err)
}
return nil
}

func GetRaftStatus() *raftStatus {
args := []string{"raft", "status"}
cmd := exec.Command("xenoncli", args...)
res, err := cmd.Output()
if err != nil {
log.Fatalf("failed to exec xenoncli raft status: %v", err)
}
raftStatus := raftStatus{}
if err := json.Unmarshal(res, &raftStatus); err != nil {
log.Fatalf("failed to unmarshal raft status: %v", err)
}
return &raftStatus
}

func GetRole() string {
return GetRaftStatus().State
}