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

init job #24

Merged
merged 2 commits into from
Oct 19, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
158 changes: 6 additions & 152 deletions controllers/job/init/cmd/preset/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,14 @@ package main

import (
"context"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/labring/sealos/controllers/job/init/internal/util/controller"
userv1 "github.com/labring/sealos/controllers/user/api/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"

"os"
"sigs.k8s.io/controller-runtime/pkg/client"
"time"

"github.com/google/uuid"
util "github.com/labring/sealos/controllers/job/init/internal/util/database"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
mongoOptions "go.mongodb.org/mongo-driver/mongo/options"
"github.com/labring/sealos/controllers/job/init/internal/util/database"
userv1 "github.com/labring/sealos/controllers/user/api/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
)

Expand All @@ -31,150 +21,14 @@ var (
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(userv1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
}

const MaxRetryConnectDB = 10

func main() {
// TODO do something
err := presetUser(context.Background())
err := database.PresetUser(&presetLog, context.Background())
if err != nil {
presetLog.Error(err, "failed to preset root user")
os.Exit(1)
}
presetLog.Info("preset root user successfully")
}

func createKubernetesClient() (client.Client, error) {
c, err := client.New(ctrl.GetConfigOrDie(), client.Options{})
if err != nil {
return nil, err
}
return c, nil
}

func presetUser(ctx context.Context) error {
if err := createUser(ctx); err != nil {
return err
}

//init mongodb database
client, err := initMongoDB(ctx)
defer client.Disconnect(context.Background())
if err != nil {
presetLog.Error(err, "unable to connect to database")
os.Exit(1)
}

// preset root user
uuid := uuid.New().String()
passwd := HashPassword(util.DefaultPassword, SaltKey)
user := NewUser(uuid, util.DefaultUser, util.DefaultUser, passwd, util.DefaultK8sUser)
userDB := os.Getenv("MONGO_USER_DB")
userCol := os.Getenv("MONGO_USER_COL")
collection := client.Database(userDB).Collection(userCol)

// check if the user already exists
exist := IsExists(ctx, collection)
if exist {
presetLog.Info("root user already exists")
return nil
}
// insert root user
insertResult, err := collection.InsertOne(context.Background(), user)
if err != nil {
presetLog.Error(err, "failed to insert root user")
return err
}
presetLog.Info("insert root user successfully", "insertResult", insertResult)
return nil
}

// TODO fix this
func createUser(ctx context.Context) error {
clt, err := createKubernetesClient()
if err != nil {
fmt.Printf("Error creating Kubernetes client: %v\n", err)
os.Exit(1)
}
if err := clt.Create(ctx, &userv1.User{
ObjectMeta: ctrl.ObjectMeta{
Name: controller.DefaultUser,
},
}); err != nil {
return err
}
return nil
}

func IsExists(ctx context.Context, collection *mongo.Collection) bool {
filter := bson.M{"password_user": util.DefaultUser}
var existingUser util.User
err := collection.FindOne(ctx, filter).Decode(&existingUser)
return err == nil
}

func NewUser(uid, name, passwordUser, password, k8sUser string) util.User {
return util.User{
UID: uid,
Name: name,
PasswordUser: passwordUser,
Password: password,
// to iso string
CreatedTime: time.Now().Format(time.RFC3339),
K8sUsers: []util.K8sUser{
{
Name: k8sUser,
},
},
}
}

func HashPassword(password string, saltKey string) string {
hash := sha256.New()
validSalt, err := DecodeBase64(saltKey)
if err != nil {
presetLog.Error(err, "failed to decode salt")
os.Exit(1)
}
hash.Write([]byte(password + string(validSalt)))
return hex.EncodeToString(hash.Sum(nil))
}

func DecodeBase64(s string) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(s)
if err != nil {
presetLog.Error(err, "failed to decode base64")
return nil, err
}
return data, nil
}

func initMongoDB(ctx context.Context) (*mongo.Client, error) {
var client *mongo.Client
var err error
MongoURI := os.Getenv("MONGO_URI")
clientOptions := mongoOptions.Client().ApplyURI(MongoURI)
for i := 0; i < MaxRetryConnectDB; i++ {
client, err = mongo.Connect(ctx, clientOptions)
if err != nil {
presetLog.Error(err, "failed to connect to mongo")
time.Sleep(5 * time.Second)
continue
}
err = client.Ping(ctx, nil)
if err != nil {
presetLog.Error(err, "failed to ping mongo")
time.Sleep(5 * time.Second)
continue
}
presetLog.Info("connect to mongo successfully")
break
}
if err != nil {
return nil, fmt.Errorf("failed to connect to mongo: %w", err)
}
return client, nil

}
2 changes: 1 addition & 1 deletion controllers/job/init/deploy/manifests/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ spec:
name: desktop-frontend-secret
key: password_salt
restartPolicy: OnFailure
backoffLimit: 10
backoffLimit: 10
2 changes: 1 addition & 1 deletion controllers/job/init/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ require (
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
)
2 changes: 1 addition & 1 deletion controllers/job/init/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -358,4 +358,4 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h6
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
35 changes: 35 additions & 0 deletions controllers/job/init/internal/util/controller/user.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,42 @@
package controller

import (
"context"
"fmt"
"os"

userv1 "github.com/labring/sealos/controllers/user/api/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// pre-defined user info in kubernetes

const (
DefaultUser = "admin"
)

func NewKubernetesClient() (client.Client, error) {
c, err := client.New(ctrl.GetConfigOrDie(), client.Options{})
if err != nil {
return nil, err
}
return c, nil
}

// TODO fix this
func NewUser(ctx context.Context) error {
clt, err := NewKubernetesClient()
if err != nil {
fmt.Printf("Error creating Kubernetes client: %v\n", err)
os.Exit(1)
}
if err := clt.Create(ctx, &userv1.User{
ObjectMeta: ctrl.ObjectMeta{
Name: DefaultUser,
},
}); err != nil {
return err
}
return nil
}
38 changes: 38 additions & 0 deletions controllers/job/init/internal/util/database/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package database

import (
"context"
"fmt"
"os"

"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
mongoOptions "go.mongodb.org/mongo-driver/mongo/options"
)

func InitMongoDB(ctx context.Context) (*mongo.Client, error) {
var client *mongo.Client
var err error
MongoURI := os.Getenv("MONGO_URI")
clientOptions := mongoOptions.Client().ApplyURI(MongoURI)
client, err = mongo.Connect(ctx, clientOptions)
if err != nil {
return nil, err
}
err = client.Ping(ctx, nil)
if err != nil {
return client, err
}
if err != nil {
return nil, fmt.Errorf("failed to connect to mongo: %w", err)
}
return client, nil

}

func IsExists(ctx context.Context, collection *mongo.Collection) bool {
filter := bson.M{"password_user": DefaultUser}
var existingUser User
err := collection.FindOne(ctx, filter).Decode(&existingUser)
return err == nil
}
92 changes: 90 additions & 2 deletions controllers/job/init/internal/util/database/user.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package database

import "os"
import (
"context"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"os"
"time"

var SaltKey = os.Getenv("SaltKey")
"github.com/go-logr/logr"
"github.com/google/uuid"
"github.com/labring/sealos/controllers/job/init/internal/util/controller"
)

// user stored in mongoDB.
type User struct {
UID string `bson:"uid" json:"uid"`
Name string `bson:"name" json:"name"`
Expand All @@ -18,7 +28,85 @@ type K8sUser struct {
}

const (
// pre-defined user info
DefaultUser = "admin"
DefaultPassword = "sealos2023"
DefaultK8sUser = "admin"
)

var (
SaltKey = os.Getenv("SaltKey")
)

func NewUser(uid, name, passwordUser, password, k8sUser string) User {
return User{
UID: uid,
Name: name,
PasswordUser: passwordUser,
Password: password,
// to iso string
CreatedTime: time.Now().Format(time.RFC3339),
K8sUsers: []K8sUser{
{
Name: k8sUser,
},
},
}
}

func PresetUser(presetLog *logr.Logger, ctx context.Context) error {
if err := controller.NewUser(ctx); err != nil {
return err
}

//init mongodb database
client, err := InitMongoDB(ctx)
defer client.Disconnect(context.Background())
if err != nil {
presetLog.Error(err, "unable to connect to database")
os.Exit(1)
}

// preset root user
uuid := uuid.New().String()
passwd := HashPassword(presetLog, DefaultPassword, SaltKey)
user := NewUser(uuid, DefaultUser, DefaultUser, passwd, DefaultK8sUser)
userDB := os.Getenv("MONGO_USER_DB")
userCol := os.Getenv("MONGO_USER_COL")
collection := client.Database(userDB).Collection(userCol)

// check if the user already exists
exist := IsExists(ctx, collection)
if exist {
presetLog.Info("root user already exists")
return nil
}
// insert root user
insertResult, err := collection.InsertOne(context.Background(), user)
if err != nil {
presetLog.Error(err, "failed to insert root user")
return err
}
presetLog.Info("insert root user successfully", "insertResult", insertResult)
return nil
}

func HashPassword(presetLog *logr.Logger, password string, saltKey string) string {
hash := sha256.New()
validSalt, err := DecodeBase64(presetLog, saltKey)
if err != nil {
presetLog.Error(err, "failed to decode salt")
os.Exit(1)
}
hash.Write([]byte(password + string(validSalt)))
return hex.EncodeToString(hash.Sum(nil))
}

func DecodeBase64(presetLog *logr.Logger, s string) ([]byte, error) {
data, err := base64.StdEncoding.DecodeString(s)
if err != nil {
presetLog.Error(err, "failed to decode base64")
return nil, err
}
return data, nil
}