From 6bb24975b73f118fa09384456bedfaeab0119d1a Mon Sep 17 00:00:00 2001 From: Nikolai Rodionov Date: Mon, 13 May 2024 10:41:14 +0200 Subject: [PATCH] Some refactoring to the application controller --- api/v1/application.go | 12 +++-- internal/controllers/applications.go | 74 ++++++++++++++++++---------- internal/controllers/environments.go | 5 ++ main.go | 2 +- 4 files changed, 63 insertions(+), 30 deletions(-) diff --git a/api/v1/application.go b/api/v1/application.go index 720dccc..20bf5d8 100644 --- a/api/v1/application.go +++ b/api/v1/application.go @@ -5,22 +5,28 @@ import ( "git.badhouseplants.net/softplayer/softplayer-backend/internal/controllers" proto "git.badhouseplants.net/softplayer/softplayer-go-proto/pkg/applications" + "github.com/go-logr/logr" ctrl "sigs.k8s.io/controller-runtime" ) -func NewApplicationsGrpcImpl(controller ctrl.Manager) *ApplicationServer { +func NewApplicationsGrpcImpl(controller ctrl.Manager, log logr.Logger) *ApplicationServer { return &ApplicationServer{ - controller: controller, + controller: controller, + logInstance: log, } } type ApplicationServer struct { proto.UnimplementedApplicationsServer - controller ctrl.Manager + controller ctrl.Manager + logInstance logr.Logger } // Create an environment func (app *ApplicationServer) Create(ctx context.Context, in *proto.CreateOptions) (*proto.ApplicationFull, error) { + log := app.logInstance + log.WithValues("user_id", in.GetOwnerId().GetUuid(), "environment_id", in.GetSpec().GetEnvironemntId(), "app_name", in.GetSpec().GetApplication()) + ctx = logr.NewContext(ctx, log) data := &controllers.ApplicationData{ Name: in.Metadata.Name, diff --git a/internal/controllers/applications.go b/internal/controllers/applications.go index 8a621a2..32f391c 100644 --- a/internal/controllers/applications.go +++ b/internal/controllers/applications.go @@ -9,11 +9,14 @@ import ( "strings" "text/template" + "git.badhouseplants.net/softplayer/softplayer-backend/internal/consts" "git.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/helm" "git.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/kube" "git.badhouseplants.net/softplayer/softplayer-backend/internal/types/helmrelease" + "github.com/go-logr/logr" + "github.com/go-logr/zapr" "github.com/google/uuid" - "github.com/sirupsen/logrus" + "go.uber.org/zap" "gopkg.in/yaml.v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,11 +46,16 @@ type ApplicationData struct { // Create environment should create a new configmap in the user's namespace // using a token that belongs to the user. func (app *Application) Create(ctx context.Context) error { + log, err := logr.FromContext(ctx) + if err != nil { + zapLog, err := zap.NewDevelopment() + if err != nil { + panic(fmt.Sprintf("who watches the watchmen (%v)?", err)) + } + log = zapr.NewLogger(zapLog) + } + app.Data.UUID = uuid.New().String() - // if err := app.isNsVerified(ctx); err != nil { - // log.Println("Can't verify ns") - // return err - // } app.Controller.GetClient() conf := &rest.Config{ @@ -65,6 +73,7 @@ func (app *Application) Create(ctx context.Context) error { } helmEntry := helm.NewHelm() + // TODO: It should be possible to use other repos release := &helm.ReleaseData{ Name: app.Data.Name, Chart: app.Data.Application, @@ -73,26 +82,36 @@ func (app *Application) Create(ctx context.Context) error { RepositoryKind: "oci", RepositoryName: "softplayer", } - goPath := os.TempDir() + "/softplayer" + formattedName := strings.ToLower( + b64.StdEncoding.EncodeToString( + []byte(app.Data.Application + app.Data.Name + app.Data.Name + app.Data.Environemnt), + ), + )[0:20] + + goPath := os.TempDir() + "/softplayer/" + formattedName if err := os.MkdirAll(goPath, 0777); err != nil { return err } + path, err := helmEntry.PullChart(goPath, release) if err != nil { - logrus.Error("0") - return err + log.Error(err, "Couldn't pull the chart") + return consts.ErrSystemError } + prettyCfgSupport := true + cfgSchema := map[string]*helmrelease.PrettyConfigSchema{} cfgSchemaPath, err := os.ReadFile(fmt.Sprintf("%s/%s/config.yaml", goPath, path)) if err != nil { - logrus.Errorf("yamlFile.Get err #%v ", err) - } - logrus.Info(string(cfgSchemaPath)) - cfgSchema := map[string]*helmrelease.PrettyConfigSchema{} - err = yaml.Unmarshal(cfgSchemaPath, cfgSchema) - if err != nil { - logrus.Error("1") - return err + log.Error(err, "Couldn't find the config file") + prettyCfgSupport = false + } else { + cfgSchema := map[string]*helmrelease.PrettyConfigSchema{} + err = yaml.Unmarshal(cfgSchemaPath, cfgSchema) + if err != nil { + log.Error(err, "Couldn't parse the pretty config") + return err + } } cfg := &helmrelease.HelmRelease{ @@ -103,13 +122,14 @@ func (app *Application) Create(ctx context.Context) error { Version: app.Data.Version, }, Repo: helmrelease.Repo{ - URL: "oci://registry.badhouseplants.net/softplayer/helm", - Type: "oci", + URL: release.RepositoryURL, + Type: release.RepositoryKind, }, }, Config: helmrelease.Config{}, } - if len(app.Data.Config) > 0 { + + if len(app.Data.Config) > 0 && prettyCfgSupport { for key, val := range app.Data.Config { value, ok := cfgSchema[key] if !ok { @@ -117,11 +137,13 @@ func (app *Application) Create(ctx context.Context) error { } tmpl, err := template.New("prettyconfig").Parse(val) if err != nil { - panic(err) + log.Error(err, "Coudln't build a tempalte for prettyconfig") + return consts.ErrSystemError } var tmplRes bytes.Buffer if err := tmpl.Execute(&tmplRes, app.Data); err != nil { - return err + log.Error(err, "Couldn't execute the prettyconfig template") + return consts.ErrSystemError } cfg.Config.Pretty = append(cfg.Config.Pretty, helmrelease.PrettyConfig{ @@ -136,12 +158,10 @@ func (app *Application) Create(ctx context.Context) error { cfgYaml, err := yaml.Marshal(cfg) if err != nil { - logrus.Error("2") - return err + log.Error(err, "Couldn't marshall a pretty config into a struct") + return consts.ErrSystemError } - logrus.Info(string(cfgYaml)) - formattedName := strings.ToLower(b64.StdEncoding.EncodeToString([]byte(app.Data.Application + app.Data.Name))) appSecret := corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: formattedName[0:20], @@ -150,6 +170,7 @@ func (app *Application) Create(ctx context.Context) error { "component": "install", "kind": "action", "environment": app.Data.Environemnt, + "uuid": app.Data.UUID, }, }, StringData: map[string]string{ @@ -158,7 +179,8 @@ func (app *Application) Create(ctx context.Context) error { } if err := kube.Create(ctx, controller.GetClient(), &appSecret, false); err != nil { - return err + log.Error(err, "Couldn't create a configmap") + return consts.ErrSystemError } return nil diff --git a/internal/controllers/environments.go b/internal/controllers/environments.go index 54ec429..f16cb30 100644 --- a/internal/controllers/environments.go +++ b/internal/controllers/environments.go @@ -18,6 +18,7 @@ import ( "git.badhouseplants.net/softplayer/softplayer-backend/internal/consts" "git.badhouseplants.net/softplayer/softplayer-backend/internal/helpers/kube" corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -80,6 +81,10 @@ func (env *Environemnt) isNsVerified(ctx context.Context) error { ns, err := clientset.CoreV1().Namespaces().Get(ctx, env.UserID, metav1.GetOptions{}) if err != nil { log.Error(err, "Couldn't get a user's namespace") + if k8serrors.IsNotFound(err) { + err := errors.New("user not found by ID") + return status.Error(codes.NotFound, err.Error()) + } return consts.ErrSystemError } diff --git a/main.go b/main.go index f941fdd..a9482aa 100644 --- a/main.go +++ b/main.go @@ -100,7 +100,7 @@ func server(params Serve) error { environments.RegisterEnvironmentsServer(grpcServer, v1.NewapiGrpcImpl(controller, log)) accounts.RegisterAccountsServer(grpcServer, v1.NewAccountRPCImpl(controller, params.HashCost)) email_proto.RegisterEmailValidationServer(grpcServer, v1.InitEmailServer(controller, &emailConfig, params.DevMode)) - applications_proto.RegisterApplicationsServer(grpcServer, v1.NewApplicationsGrpcImpl(controller)) + applications_proto.RegisterApplicationsServer(grpcServer, v1.NewApplicationsGrpcImpl(controller, log)) if err := grpcServer.Serve(lis); err != nil { return err