diff --git a/cmd/main.go b/cmd/main.go index 25f92fa..bae09af 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -46,7 +46,7 @@ func main() { log := logging.New(nil) log.Info("loading config") - config, err := config.LoadConfig() + config, err := config.LoadEnvConfig() if err != nil { return fmt.Errorf("loading config: %w", err) } diff --git a/go.mod b/go.mod index c988aa7..3691514 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -58,6 +58,7 @@ require ( github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/speakeasy-api/jsonpath v0.6.0 // indirect github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect github.com/spf13/pflag v1.0.6 // indirect @@ -72,7 +73,7 @@ require ( golang.org/x/sys v0.39.0 // indirect golang.org/x/term v0.38.0 // indirect golang.org/x/text v0.32.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/time v0.11.0 // indirect golang.org/x/tools v0.39.0 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/go.sum b/go.sum index 97c0e5c..eb24c4c 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -163,8 +163,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -254,8 +254,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= diff --git a/internal/api/openapi/branch.go b/internal/api/openapi/branch.go index 11fe93b..ba8b2a3 100644 --- a/internal/api/openapi/branch.go +++ b/internal/api/openapi/branch.go @@ -71,9 +71,9 @@ func (Server) DeleteBranch(ctx context.Context, request DeleteBranchRequestObjec // Get services env.Logger.DebugContext(ctx, "getting services") - services, err := env.Database.GetServicesByProject( + services, err := env.Database.GetKubernetesServicesByProject( ctx, - database.GetServicesByProjectParams{ + database.GetKubernetesServicesByProjectParams{ ProjectID: project.ID, ProjectBranch: request.Params.Branch, }) if err != nil { @@ -104,7 +104,7 @@ func (Server) DeleteBranch(ctx context.Context, request DeleteBranchRequestObjec env.Logger.ErrorContext(ctx, "failed to delete ingress", slog.Any("error", err)) } } - err = env.Database.DeleteServiceById(ctx, svc.ID) + err = env.Database.DeleteKubernetesServiceById(ctx, svc.ID) if err != nil { env.Logger.ErrorContext(ctx, "failed to delete service", slog.Any("error", err)) return DeleteBranch500JSONResponse{ @@ -116,9 +116,9 @@ func (Server) DeleteBranch(ctx context.Context, request DeleteBranchRequestObjec } } - ids, err := env.Database.GetUnusedVolumeIdentifiers( + ids, err := env.Database.GetUnusedKubernetesVolumeIdentifiers( ctx, - database.GetUnusedVolumeIdentifiersParams{ + database.GetUnusedKubernetesVolumeIdentifiersParams{ ProjectID: project.ID, ProjectBranch: request.Params.Branch, ExcludeVolumes: nil, @@ -139,8 +139,8 @@ func (Server) DeleteBranch(ctx context.Context, request DeleteBranchRequestObjec env.Logger.ErrorContext(ctx, "failed to delete pvc", slog.Any("error", err)) } } - err = env.Database.DeleteUnusedVolumes(ctx, - database.DeleteUnusedVolumesParams{ + err = env.Database.DeleteUnusedKubernetesVolumes(ctx, + database.DeleteUnusedKubernetesVolumesParams{ ProjectID: project.ID, ProjectBranch: request.Params.Branch, ExcludeVolumes: nil, diff --git a/internal/api/openapi/deploy.go b/internal/api/openapi/deploy.go index d441d66..3aafeda 100644 --- a/internal/api/openapi/deploy.go +++ b/internal/api/openapi/deploy.go @@ -10,10 +10,10 @@ import ( apierror "nimbus/internal/api/error" "nimbus/internal/api/requestid" + "nimbus/internal/config" "nimbus/internal/database" "nimbus/internal/env" "nimbus/internal/kubernetes" - "nimbus/internal/models" "nimbus/internal/utils" "github.com/goccy/go-yaml" @@ -23,7 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" ) -func shouldCreateKubeService(service *models.Service) bool { +func shouldCreateKubeService(service *config.Service) bool { if len(service.Network.Ports) > 0 { return true } @@ -107,8 +107,8 @@ func (Server) PostDeploy( } env.Logger.DebugContext(ctx, "unmarshaling yaml", slog.String("filename", fileheader.Filename)) - var config models.Config - err = yaml.Unmarshal(content, &config) + var nimbusConfig config.Nimbus + err = yaml.Unmarshal(content, &nimbusConfig) if err != nil { env.Logger.ErrorContext(ctx, "failed to unmarshal yaml", slog.String("filename", fileheader.Filename), @@ -120,7 +120,7 @@ func (Server) PostDeploy( ErrorId: requestID, }, nil } - if config.AppName == "" { + if nimbusConfig.AppName == "" { env.Logger.ErrorContext(ctx, "app name is missing in config", slog.String("filename", fileheader.Filename)) return PostDeploy400JSONResponse{ @@ -130,21 +130,21 @@ func (Server) PostDeploy( ErrorId: requestID, }, nil } - if config.AllowBranchPreviews == nil { + if nimbusConfig.AllowBranchPreviews == nil { v := true - config.AllowBranchPreviews = &v + nimbusConfig.AllowBranchPreviews = &v env.Logger.DebugContext(ctx, "defaulting AllowBranchPreviews to true", - slog.String("app", config.AppName)) + slog.String("app", nimbusConfig.AppName)) } // Retrieve project - var deployRequest models.DeployRequest + var deployRequest config.DeployRequest env.Logger.DebugContext( - ctx, "retrieving project by name", slog.String("name", config.AppName)) - project, err := env.Database.GetProjectByName(ctx, config.AppName) + ctx, "retrieving project by name", slog.String("name", nimbusConfig.AppName)) + project, err := env.Database.GetProjectByName(ctx, nimbusConfig.AppName) if errors.Is(err, pgx.ErrNoRows) { env.Logger.ErrorContext(ctx, "project not found", - slog.String("app", config.AppName), + slog.String("app", nimbusConfig.AppName), slog.Any("error", err)) return PostDeploy404JSONResponse{ Status: apierror.ProjectNotFound.Status(), @@ -154,7 +154,7 @@ func (Server) PostDeploy( }, nil } else if err != nil { env.Logger.ErrorContext(ctx, "failed to get project", - slog.String("app", config.AppName), + slog.String("app", nimbusConfig.AppName), slog.Any("error", err)) return PostDeploy500JSONResponse{ Status: apierror.InternalServerError.Status(), @@ -206,8 +206,8 @@ func (Server) PostDeploy( } else { deployRequest.BranchName = branches[0] } - if config.AllowBranchPreviews != nil && - !*config.AllowBranchPreviews && + if nimbusConfig.AllowBranchPreviews != nil && + !*nimbusConfig.AllowBranchPreviews && deployRequest.BranchName != "main" && deployRequest.BranchName != "master" { return PostDeploy409JSONResponse{ Status: apierror.DisabledBranchPreview.Status(), @@ -221,10 +221,11 @@ func (Server) PostDeploy( env.Logger.DebugContext(ctx, "getting project services", slog.String("project", project.Name), slog.String("branch", deployRequest.BranchName)) - servicesList, err := env.Database.GetServicesByProject(ctx, database.GetServicesByProjectParams{ - ProjectID: deployRequest.ProjectID, - ProjectBranch: deployRequest.BranchName, - }) + servicesList, err := env.Database.GetKubernetesServicesByProject(ctx, + database.GetKubernetesServicesByProjectParams{ + ProjectID: deployRequest.ProjectID, + ProjectBranch: deployRequest.BranchName, + }) if err != nil { env.Logger.ErrorContext(ctx, "failed to get project services", slog.String("project", project.Name), @@ -254,7 +255,7 @@ func (Server) PostDeploy( ErrorId: requestID, }, nil } - for i, service := range config.Services { + for i, service := range nimbusConfig.Services { for j, variable := range service.Env { key, prefFound := strings.CutPrefix(variable.Value, "${") key, suffFound := strings.CutSuffix(key, "}") @@ -262,7 +263,7 @@ func (Server) PostDeploy( continue } if secretVal, ok := secrets[key]; ok { - config.Services[i].Env[j].Value = secretVal + nimbusConfig.Services[i].Env[j].Value = secretVal } } } @@ -285,7 +286,7 @@ func (Server) PostDeploy( }, nil } if created && deployRequest.BranchName != "main" && deployRequest.BranchName != "master" { - mainNS := utils.GetSanitizedNamespace(config.AppName, "main") + mainNS := utils.GetSanitizedNamespace(nimbusConfig.AppName, "main") vals, err := kubernetes.GetSecretValues(ctx, mainNS, env) if err != nil { env.Logger.ErrorContext(ctx, "failed to get secret values", @@ -301,12 +302,12 @@ func (Server) PostDeploy( } if len(vals) > 0 { err = kubernetes.UpdateSecret( - ctx, deployRequest.Namespace, fmt.Sprintf("%s-env", config.AppName), + ctx, deployRequest.Namespace, fmt.Sprintf("%s-env", nimbusConfig.AppName), vals, env) if err != nil { env.Logger.ErrorContext(ctx, "failed to update secrets", slog.String("namespace", deployRequest.Namespace), - slog.String("app", config.AppName), + slog.String("app", nimbusConfig.AppName), slog.Any("error", err)) return PostDeploy500JSONResponse{ Status: apierror.InternalServerError.Status(), @@ -319,7 +320,7 @@ func (Server) PostDeploy( } // Delete removed services - existingServices := make(map[string]*database.Service) + existingServices := make(map[string]*database.KubernetesService) for _, service := range deployRequest.ExistingServices { existingServices[service.ServiceName] = &service } @@ -327,7 +328,7 @@ func (Server) PostDeploy( slog.String("project", project.Name), slog.String("branch", deployRequest.BranchName)) serviceNames := make(map[string]bool) - for _, service := range config.Services { + for _, service := range nimbusConfig.Services { if serviceNames[service.Name] { env.Logger.ErrorContext(ctx, "duplicate service name", slog.String("service", service.Name)) return PostDeploy422JSONResponse{ @@ -399,7 +400,7 @@ func (Server) PostDeploy( env.Logger.DebugContext(ctx, "deleting service in database", slog.String("service", service.ServiceName)) - err = env.Database.DeleteServiceById(ctx, service.ID) + err = env.Database.DeleteKubernetesServiceById(ctx, service.ID) if err != nil { env.Logger.ErrorContext(ctx, "failed to delete service", slog.String("service", service.ServiceName), @@ -418,7 +419,7 @@ func (Server) PostDeploy( slog.String("project", project.Name), slog.String("branch", deployRequest.BranchName)) serviceUrls := make(map[string][]string) - for _, serviceConfig := range config.Services { + for _, serviceConfig := range nimbusConfig.Services { // Create deployment env.Logger.DebugContext(ctx, "creating deployment", @@ -455,7 +456,8 @@ func (Server) PostDeploy( if shouldCreateKubeService(&serviceConfig) { env.Logger.DebugContext(ctx, "creating service", slog.String("service", serviceConfig.Name)) - serviceSpec, err := kubernetes.GenerateServiceSpec(deployRequest.Namespace, &serviceConfig, oldService) + serviceSpec, err := kubernetes.GenerateServiceSpec(deployRequest.Namespace, + &serviceConfig, oldService) if err != nil { env.Logger.ErrorContext(ctx, "failed to generate service spec", slog.String("service", serviceConfig.Name), @@ -482,16 +484,17 @@ func (Server) PostDeploy( } var urls []string - var newSvc database.Service + var newSvc database.KubernetesService if !svcExists { env.Logger.DebugContext(ctx, "creating service in database", slog.String("service", serviceConfig.Name)) - newSvc, err = env.Database.CreateService(ctx, database.CreateServiceParams{ - ID: uuid.New(), - ProjectID: deployRequest.ProjectID, - ProjectBranch: deployRequest.BranchName, - ServiceName: serviceConfig.Name, - }) + newSvc, err = env.Database.CreateKubernetesService(ctx, + database.CreateKubernetesServiceParams{ + ID: uuid.New(), + ProjectID: deployRequest.ProjectID, + ProjectBranch: deployRequest.BranchName, + ServiceName: serviceConfig.Name, + }) if err != nil { env.Logger.ErrorContext(ctx, "failed to create service in database", slog.String("service", serviceConfig.Name), @@ -522,10 +525,11 @@ func (Server) PostDeploy( if serviceConfig.Template != "http" { env.Logger.DebugContext(ctx, "no service ports specified - clearing node ports", slog.String("service", serviceConfig.Name)) - err := env.Database.SetServiceNodePorts(ctx, database.SetServiceNodePortsParams{ - ID: serviceID, - NodePorts: []int32{}, - }) + err := env.Database.SetKubernetesServiceNodePorts(ctx, + database.SetKubernetesServiceNodePortsParams{ + ID: serviceID, + NodePorts: []int32{}, + }) if err != nil { env.Logger.ErrorContext(ctx, "failed to clear service ports", slog.String("service", serviceConfig.Name), @@ -556,10 +560,11 @@ func (Server) PostDeploy( }, nil } } - err = env.Database.SetServiceIngress(ctx, database.SetServiceIngressParams{ - ID: serviceID, - Ingress: pgtype.Text{Valid: false}, - }) + err = env.Database.SetKubernetesServiceIngress(ctx, + database.SetKubernetesServiceIngressParams{ + ID: serviceID, + Ingress: pgtype.Text{Valid: false}, + }) if err != nil { env.Logger.ErrorContext(ctx, "failed to set ingress", slog.String("service", serviceConfig.Name), @@ -580,10 +585,11 @@ func (Server) PostDeploy( if !serviceConfig.Public { env.Logger.DebugContext(ctx, "clearing node ports for private service", slog.String("service", serviceConfig.Name)) - err := env.Database.SetServiceNodePorts(ctx, database.SetServiceNodePortsParams{ - ID: serviceID, - NodePorts: []int32{}, - }) + err := env.Database.SetKubernetesServiceNodePorts(ctx, + database.SetKubernetesServiceNodePortsParams{ + ID: serviceID, + NodePorts: []int32{}, + }) if err != nil { env.Logger.ErrorContext(ctx, "failed to update service in database", slog.String("service", serviceConfig.Name), @@ -606,10 +612,11 @@ func (Server) PostDeploy( nodePorts = append(nodePorts, port.NodePort) urls = append(urls, utils.FormatServiceURL(env.Config.Domain, port.NodePort)) } - err = env.Database.SetServiceNodePorts(ctx, database.SetServiceNodePortsParams{ - ID: serviceID, - NodePorts: nodePorts, - }) + err = env.Database.SetKubernetesServiceNodePorts(ctx, + database.SetKubernetesServiceNodePortsParams{ + ID: serviceID, + NodePorts: nodePorts, + }) if err != nil { env.Logger.ErrorContext( ctx, "failed to update service node ports in database", slog.Any("error", err)) @@ -640,7 +647,7 @@ func (Server) PostDeploy( }, nil } } - err = env.Database.SetServiceIngress(ctx, database.SetServiceIngressParams{ + err = env.Database.SetKubernetesServiceIngress(ctx, database.SetKubernetesServiceIngressParams{ ID: serviceID, Ingress: pgtype.Text{Valid: false}, }) @@ -685,10 +692,11 @@ func (Server) PostDeploy( ErrorId: requestID, }, nil } - err = env.Database.SetServiceIngress(ctx, database.SetServiceIngressParams{ - ID: serviceID, - Ingress: pgtype.Text{String: newIngress.Spec.Rules[0].Host, Valid: true}, - }) + err = env.Database.SetKubernetesServiceIngress(ctx, + database.SetKubernetesServiceIngressParams{ + ID: serviceID, + Ingress: pgtype.Text{String: newIngress.Spec.Rules[0].Host, Valid: true}, + }) if err != nil { env.Logger.ErrorContext(ctx, "failed to update ingress in database", slog.String("service", serviceConfig.Name), diff --git a/internal/api/openapi/projects.go b/internal/api/openapi/projects.go index 66ee7ab..022fe72 100644 --- a/internal/api/openapi/projects.go +++ b/internal/api/openapi/projects.go @@ -112,7 +112,7 @@ func (Server) DeleteProjectsName( // Get project branches env.Logger.DebugContext(ctx, "getting project branches") - branches, err := env.Database.GetProjectBranches(ctx, project.ID) + branches, err := env.Database.GetKubernetesProjectBranches(ctx, project.ID) if err != nil { env.Logger.ErrorContext(ctx, "failed to get project branches", slog.Any("error", err)) return DeleteProjectsName500JSONResponse{ @@ -124,9 +124,9 @@ func (Server) DeleteProjectsName( } for _, branch := range branches { - services, err := env.Database.GetServicesByProject( + services, err := env.Database.GetKubernetesServicesByProject( ctx, - database.GetServicesByProjectParams{ + database.GetKubernetesServicesByProjectParams{ ProjectID: project.ID, ProjectBranch: branch, }) @@ -157,7 +157,7 @@ func (Server) DeleteProjectsName( env.Logger.ErrorContext(ctx, "failed to delete ingress", slog.Any("error", err)) } } - err = env.Database.DeleteServiceById(ctx, svc.ID) + err = env.Database.DeleteKubernetesServiceById(ctx, svc.ID) if err != nil { env.Logger.ErrorContext(ctx, "failed to delete service from database", slog.Any("error", err)) return DeleteProjectsName500JSONResponse{ @@ -170,9 +170,9 @@ func (Server) DeleteProjectsName( } // Delete volumes - ids, err := env.Database.GetUnusedVolumeIdentifiers( + ids, err := env.Database.GetUnusedKubernetesVolumeIdentifiers( ctx, - database.GetUnusedVolumeIdentifiersParams{ + database.GetUnusedKubernetesVolumeIdentifiersParams{ ProjectID: project.ID, ProjectBranch: branch, ExcludeVolumes: nil, }) if err != nil { @@ -190,9 +190,9 @@ func (Server) DeleteProjectsName( env.Logger.ErrorContext(ctx, "failed to delete pvc", slog.Any("error", err)) } } - err = env.Database.DeleteUnusedVolumes( + err = env.Database.DeleteUnusedKubernetesVolumes( ctx, - database.DeleteUnusedVolumesParams{ + database.DeleteUnusedKubernetesVolumesParams{ ProjectID: project.ID, ProjectBranch: branch, ExcludeVolumes: nil, }) if err != nil { @@ -398,7 +398,7 @@ func (Server) PutProjectsNameSecrets( // Get project branches env.Logger.DebugContext(ctx, "getting project branches") - branches, err := env.Database.GetProjectBranches(ctx, project.ID) + branches, err := env.Database.GetKubernetesProjectBranches(ctx, project.ID) if err != nil { env.Logger.ErrorContext(ctx, "failed to get project branches", slog.Any("error", err)) return PutProjectsNameSecrets500JSONResponse{ diff --git a/internal/api/openapi/services.go b/internal/api/openapi/services.go index d1daf0f..ce8ff1d 100644 --- a/internal/api/openapi/services.go +++ b/internal/api/openapi/services.go @@ -62,7 +62,7 @@ func (Server) GetServices( requestid := fmt.Sprintf("%d", requestid.FromContext(ctx)) user := database.UserFromContext(ctx) - services, err := env.Database.GetServicesByUser(ctx, user.ID) + services, err := env.Database.GetKubernetesServicesByUser(ctx, user.ID) if err != nil { env.Logger.ErrorContext(ctx, "failed to get services", slog.String("user_id", user.ID.String()), @@ -170,10 +170,11 @@ func (Server) GetServicesName( env.Logger.DebugContext(ctx, "getting service", slog.String("service", request.Name), slog.String("project", project.Name)) - svc, err := env.Database.GetServiceByName(ctx, database.GetServiceByNameParams{ - ServiceName: request.Name, - ProjectID: project.ID, - }) + svc, err := env.Database.GetKubernetesServiceByName(ctx, + database.GetKubernetesServiceByNameParams{ + ServiceName: request.Name, + ProjectID: project.ID, + }) if errors.Is(err, pgx.ErrNoRows) { env.Logger.ErrorContext(ctx, "service not found", slog.String("service", request.Name), diff --git a/internal/config/config.go b/internal/config/config.go index ea3adc9..edbf19b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -34,7 +34,7 @@ type Database struct { Password string `validate:"required"` } -type Config struct { +type EnvConfig struct { Environment string `validate:"omitempty,oneof=development production"` Domain string `validate:"required,hostname_rfc1123"` NimbusStorageClass string @@ -49,8 +49,8 @@ func loadWithDefault(key, def string) string { return val } -func LoadConfig() (Config, error) { - conf := Config{ +func LoadEnvConfig() (EnvConfig, error) { + conf := EnvConfig{ Environment: loadWithDefault("ENVIRONMENT", "development"), Domain: loadWithDefault("DOMAIN", ""), NimbusStorageClass: loadWithDefault("NIMBUS_STORAGE_CLASS", ""), diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 2e73925..994dd0c 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -10,7 +10,7 @@ func TestLoadConfig(t *testing.T) { name string setup func(*testing.T) wantError bool - validate func(*testing.T, *Config) + validate func(*testing.T, *EnvConfig) }{ { name: "valid config - all fields filled", @@ -25,7 +25,7 @@ func TestLoadConfig(t *testing.T) { t.Setenv("DB_PASSWORD", "password") }, wantError: false, - validate: func(t *testing.T, config *Config) { + validate: func(t *testing.T, config *EnvConfig) { if config.Environment != "development" { t.Errorf("expected Environment %s, got %s", "development", config.Environment) } @@ -64,7 +64,7 @@ func TestLoadConfig(t *testing.T) { t.Setenv("DB_PASSWORD", "password") }, wantError: false, - validate: func(t *testing.T, config *Config) { + validate: func(t *testing.T, config *EnvConfig) { if config.Environment != "production" { t.Errorf("expected Environment %s, got %s", "production", config.Environment) } @@ -80,7 +80,7 @@ func TestLoadConfig(t *testing.T) { t.Setenv("DB_PASSWORD", "password") }, wantError: false, - validate: func(t *testing.T, config *Config) { + validate: func(t *testing.T, config *EnvConfig) { if config.Environment != "development" { t.Errorf("expected default Environment %s, got %s", "development", config.Environment) } @@ -232,7 +232,7 @@ func TestLoadConfig(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.setup(t) - config, err := LoadConfig() + config, err := LoadEnvConfig() if tt.wantError { if err == nil { @@ -385,7 +385,7 @@ func TestErrorMessages(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.setup(t) - _, err := LoadConfig() + _, err := LoadEnvConfig() if err == nil { t.Fatal("expected error, got nil") @@ -500,7 +500,7 @@ func TestValidatePort(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.setup(t) - _, err := LoadConfig() + _, err := LoadEnvConfig() if tt.wantError { if err == nil { diff --git a/internal/models/models.go b/internal/config/nimbus.go similarity index 60% rename from internal/models/models.go rename to internal/config/nimbus.go index d7a7f5f..129b642 100644 --- a/internal/models/models.go +++ b/internal/config/nimbus.go @@ -1,15 +1,63 @@ -package models +package config import ( + "encoding" + "fmt" + "strings" + "nimbus/internal/database" "github.com/google/uuid" - corev1 "k8s.io/api/core/v1" ) -type Config struct { +var ( + _ encoding.TextMarshaler = (*Runtime)(nil) + _ encoding.TextUnmarshaler = (*Runtime)(nil) +) + +type Runtime string + +const ( + RuntimeDocker = "docker" + RuntimeKubernetes = "kubernetes" +) + +func (r Runtime) MarshalText() ([]byte, error) { + switch r { + case RuntimeDocker, RuntimeKubernetes: + return []byte(r), nil + case "": + return []byte(RuntimeKubernetes), nil + default: + return nil, fmt.Errorf("invalid runtime %q", r) + } +} + +func (r *Runtime) UnmarshalText(text []byte) error { + raw := strings.TrimSpace(string(text)) + if raw == "" { + *r = RuntimeKubernetes + return nil + } + + switch strings.ToLower(raw) { + case "docker": + *r = RuntimeDocker + case "kubernetes": + *r = RuntimeKubernetes + default: + return fmt.Errorf( + "invalid runtime %q (expected one of: unknown, docker, kubernetes)", + raw, + ) + } + return nil +} + +type Nimbus struct { AppName string `yaml:"app"` + RunTime Runtime `yaml:"runtime"` // "kubernetes" (default) || "docker" AllowBranchPreviews *bool `yaml:"allowBranchPreviews,omitempty"` Services []Service `yaml:"services"` } @@ -56,7 +104,7 @@ type DeployRequest struct { Namespace string ProjectID uuid.UUID BranchName string - ProjectConfig Config + ProjectConfig Nimbus FileContent []byte - ExistingServices []database.Service + ExistingServices []database.KubernetesService } diff --git a/internal/database/models.go b/internal/database/models.go index cac77c2..d2d812d 100644 --- a/internal/database/models.go +++ b/internal/database/models.go @@ -5,10 +5,93 @@ package database import ( + "database/sql/driver" + "fmt" + "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" ) +type Runtime string + +const ( + RuntimeDocker Runtime = "docker" + RuntimeKubernetes Runtime = "kubernetes" +) + +func (e *Runtime) Scan(src interface{}) error { + switch s := src.(type) { + case []byte: + *e = Runtime(s) + case string: + *e = Runtime(s) + default: + return fmt.Errorf("unsupported scan type for Runtime: %T", src) + } + return nil +} + +type NullRuntime struct { + Runtime Runtime + Valid bool // Valid is true if Runtime is not NULL +} + +// Scan implements the Scanner interface. +func (ns *NullRuntime) Scan(value interface{}) error { + if value == nil { + ns.Runtime, ns.Valid = "", false + return nil + } + ns.Valid = true + return ns.Runtime.Scan(value) +} + +// Value implements the driver Valuer interface. +func (ns NullRuntime) Value() (driver.Value, error) { + if !ns.Valid { + return nil, nil + } + return string(ns.Runtime), nil +} + +type DockerService struct { + ID uuid.UUID + ProjectID uuid.UUID + ProjectBranch string + ServiceName string + Runtime Runtime + PortMaps []string + ContainerName pgtype.Text + DockerNetwork pgtype.Text +} + +type DockerVolume struct { + Identifier uuid.UUID + Runtime Runtime + VolumeName string + ProjectID uuid.UUID + ProjectBranch string +} + +type KubernetesService struct { + ID uuid.UUID + ProjectID uuid.UUID + ProjectBranch string + ServiceName string + Runtime Runtime + NodePorts []int32 + Ingress pgtype.Text +} + +type KubernetesVolume struct { + Identifier uuid.UUID + Runtime Runtime + VolumeName string + ProjectID uuid.UUID + ProjectBranch string + Size int32 +} + type Project struct { ID uuid.UUID Name string @@ -19,8 +102,12 @@ type Service struct { ProjectID uuid.UUID ProjectBranch string ServiceName string + Runtime Runtime NodePorts []int32 Ingress pgtype.Text + PortMaps []string + ContainerName pgtype.Text + DockerNetwork pgtype.Text } type User struct { @@ -36,6 +123,7 @@ type UserProject struct { type Volume struct { Identifier uuid.UUID + Runtime Runtime VolumeName string ProjectID uuid.UUID ProjectBranch string diff --git a/internal/database/querier.go b/internal/database/querier.go index 058e489..a65463b 100644 --- a/internal/database/querier.go +++ b/internal/database/querier.go @@ -13,29 +13,28 @@ import ( type Querier interface { AddUserToProject(ctx context.Context, arg AddUserToProjectParams) error CheckProjectsTableExists(ctx context.Context) (bool, error) + CreateKubernetesService(ctx context.Context, arg CreateKubernetesServiceParams) (KubernetesService, error) + CreateKubernetesVolume(ctx context.Context, arg CreateKubernetesVolumeParams) (Volume, error) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) - CreateService(ctx context.Context, arg CreateServiceParams) (Service, error) - CreateVolume(ctx context.Context, arg CreateVolumeParams) (Volume, error) + DeleteKubernetesServiceById(ctx context.Context, id uuid.UUID) error + DeleteKubernetesServiceByName(ctx context.Context, arg DeleteKubernetesServiceByNameParams) error DeleteProject(ctx context.Context, id uuid.UUID) error - DeleteServiceById(ctx context.Context, id uuid.UUID) error - DeleteServiceByName(ctx context.Context, arg DeleteServiceByNameParams) error - DeleteUnusedVolumes(ctx context.Context, arg DeleteUnusedVolumesParams) error + DeleteUnusedKubernetesVolumes(ctx context.Context, arg DeleteUnusedKubernetesVolumesParams) error GetApiKeyExistance(ctx context.Context, apiKey string) (bool, error) + GetKubernetesProjectBranches(ctx context.Context, projectID uuid.UUID) ([]string, error) + GetKubernetesServiceByName(ctx context.Context, arg GetKubernetesServiceByNameParams) (KubernetesService, error) + GetKubernetesServicesByProject(ctx context.Context, arg GetKubernetesServicesByProjectParams) ([]KubernetesService, error) + GetKubernetesServicesByUser(ctx context.Context, userID uuid.UUID) ([]GetKubernetesServicesByUserRow, error) + GetKubernetesVolumeIdentifier(ctx context.Context, arg GetKubernetesVolumeIdentifierParams) (uuid.UUID, error) GetProject(ctx context.Context, id uuid.UUID) (Project, error) - GetProjectBranches(ctx context.Context, projectID uuid.UUID) ([]string, error) GetProjectById(ctx context.Context, id uuid.UUID) (Project, error) GetProjectByName(ctx context.Context, name string) (Project, error) GetProjectsByUser(ctx context.Context, userID uuid.UUID) ([]Project, error) - GetService(ctx context.Context, id uuid.UUID) (Service, error) - GetServiceByName(ctx context.Context, arg GetServiceByNameParams) (Service, error) - GetServicesByProject(ctx context.Context, arg GetServicesByProjectParams) ([]Service, error) - GetServicesByUser(ctx context.Context, userID uuid.UUID) ([]GetServicesByUserRow, error) - GetUnusedVolumeIdentifiers(ctx context.Context, arg GetUnusedVolumeIdentifiersParams) ([]uuid.UUID, error) + GetUnusedKubernetesVolumeIdentifiers(ctx context.Context, arg GetUnusedKubernetesVolumeIdentifiersParams) ([]uuid.UUID, error) GetUserByApiKey(ctx context.Context, apiKey string) (User, error) - GetVolumeIdentifier(ctx context.Context, arg GetVolumeIdentifierParams) (uuid.UUID, error) IsUserInProject(ctx context.Context, arg IsUserInProjectParams) (bool, error) - SetServiceIngress(ctx context.Context, arg SetServiceIngressParams) error - SetServiceNodePorts(ctx context.Context, arg SetServiceNodePortsParams) error + SetKubernetesServiceIngress(ctx context.Context, arg SetKubernetesServiceIngressParams) error + SetKubernetesServiceNodePorts(ctx context.Context, arg SetKubernetesServiceNodePortsParams) error } var _ Querier = (*Queries)(nil) diff --git a/internal/database/queriermock.go b/internal/database/queriermock.go index b333371..d2334ed 100644 --- a/internal/database/queriermock.go +++ b/internal/database/queriermock.go @@ -70,105 +70,105 @@ func (mr *MockQuerierMockRecorder) CheckProjectsTableExists(ctx any) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckProjectsTableExists", reflect.TypeOf((*MockQuerier)(nil).CheckProjectsTableExists), ctx) } -// CreateProject mocks base method. -func (m *MockQuerier) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) { +// CreateKubernetesService mocks base method. +func (m *MockQuerier) CreateKubernetesService(ctx context.Context, arg CreateKubernetesServiceParams) (KubernetesService, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateProject", ctx, arg) - ret0, _ := ret[0].(Project) + ret := m.ctrl.Call(m, "CreateKubernetesService", ctx, arg) + ret0, _ := ret[0].(KubernetesService) ret1, _ := ret[1].(error) return ret0, ret1 } -// CreateProject indicates an expected call of CreateProject. -func (mr *MockQuerierMockRecorder) CreateProject(ctx, arg any) *gomock.Call { +// CreateKubernetesService indicates an expected call of CreateKubernetesService. +func (mr *MockQuerierMockRecorder) CreateKubernetesService(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateProject", reflect.TypeOf((*MockQuerier)(nil).CreateProject), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateKubernetesService", reflect.TypeOf((*MockQuerier)(nil).CreateKubernetesService), ctx, arg) } -// CreateService mocks base method. -func (m *MockQuerier) CreateService(ctx context.Context, arg CreateServiceParams) (Service, error) { +// CreateKubernetesVolume mocks base method. +func (m *MockQuerier) CreateKubernetesVolume(ctx context.Context, arg CreateKubernetesVolumeParams) (Volume, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateService", ctx, arg) - ret0, _ := ret[0].(Service) + ret := m.ctrl.Call(m, "CreateKubernetesVolume", ctx, arg) + ret0, _ := ret[0].(Volume) ret1, _ := ret[1].(error) return ret0, ret1 } -// CreateService indicates an expected call of CreateService. -func (mr *MockQuerierMockRecorder) CreateService(ctx, arg any) *gomock.Call { +// CreateKubernetesVolume indicates an expected call of CreateKubernetesVolume. +func (mr *MockQuerierMockRecorder) CreateKubernetesVolume(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateService", reflect.TypeOf((*MockQuerier)(nil).CreateService), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateKubernetesVolume", reflect.TypeOf((*MockQuerier)(nil).CreateKubernetesVolume), ctx, arg) } -// CreateVolume mocks base method. -func (m *MockQuerier) CreateVolume(ctx context.Context, arg CreateVolumeParams) (Volume, error) { +// CreateProject mocks base method. +func (m *MockQuerier) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateVolume", ctx, arg) - ret0, _ := ret[0].(Volume) + ret := m.ctrl.Call(m, "CreateProject", ctx, arg) + ret0, _ := ret[0].(Project) ret1, _ := ret[1].(error) return ret0, ret1 } -// CreateVolume indicates an expected call of CreateVolume. -func (mr *MockQuerierMockRecorder) CreateVolume(ctx, arg any) *gomock.Call { +// CreateProject indicates an expected call of CreateProject. +func (mr *MockQuerierMockRecorder) CreateProject(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateVolume", reflect.TypeOf((*MockQuerier)(nil).CreateVolume), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateProject", reflect.TypeOf((*MockQuerier)(nil).CreateProject), ctx, arg) } -// DeleteProject mocks base method. -func (m *MockQuerier) DeleteProject(ctx context.Context, id uuid.UUID) error { +// DeleteKubernetesServiceById mocks base method. +func (m *MockQuerier) DeleteKubernetesServiceById(ctx context.Context, id uuid.UUID) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteProject", ctx, id) + ret := m.ctrl.Call(m, "DeleteKubernetesServiceById", ctx, id) ret0, _ := ret[0].(error) return ret0 } -// DeleteProject indicates an expected call of DeleteProject. -func (mr *MockQuerierMockRecorder) DeleteProject(ctx, id any) *gomock.Call { +// DeleteKubernetesServiceById indicates an expected call of DeleteKubernetesServiceById. +func (mr *MockQuerierMockRecorder) DeleteKubernetesServiceById(ctx, id any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteProject", reflect.TypeOf((*MockQuerier)(nil).DeleteProject), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteKubernetesServiceById", reflect.TypeOf((*MockQuerier)(nil).DeleteKubernetesServiceById), ctx, id) } -// DeleteServiceById mocks base method. -func (m *MockQuerier) DeleteServiceById(ctx context.Context, id uuid.UUID) error { +// DeleteKubernetesServiceByName mocks base method. +func (m *MockQuerier) DeleteKubernetesServiceByName(ctx context.Context, arg DeleteKubernetesServiceByNameParams) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteServiceById", ctx, id) + ret := m.ctrl.Call(m, "DeleteKubernetesServiceByName", ctx, arg) ret0, _ := ret[0].(error) return ret0 } -// DeleteServiceById indicates an expected call of DeleteServiceById. -func (mr *MockQuerierMockRecorder) DeleteServiceById(ctx, id any) *gomock.Call { +// DeleteKubernetesServiceByName indicates an expected call of DeleteKubernetesServiceByName. +func (mr *MockQuerierMockRecorder) DeleteKubernetesServiceByName(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteServiceById", reflect.TypeOf((*MockQuerier)(nil).DeleteServiceById), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteKubernetesServiceByName", reflect.TypeOf((*MockQuerier)(nil).DeleteKubernetesServiceByName), ctx, arg) } -// DeleteServiceByName mocks base method. -func (m *MockQuerier) DeleteServiceByName(ctx context.Context, arg DeleteServiceByNameParams) error { +// DeleteProject mocks base method. +func (m *MockQuerier) DeleteProject(ctx context.Context, id uuid.UUID) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteServiceByName", ctx, arg) + ret := m.ctrl.Call(m, "DeleteProject", ctx, id) ret0, _ := ret[0].(error) return ret0 } -// DeleteServiceByName indicates an expected call of DeleteServiceByName. -func (mr *MockQuerierMockRecorder) DeleteServiceByName(ctx, arg any) *gomock.Call { +// DeleteProject indicates an expected call of DeleteProject. +func (mr *MockQuerierMockRecorder) DeleteProject(ctx, id any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteServiceByName", reflect.TypeOf((*MockQuerier)(nil).DeleteServiceByName), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteProject", reflect.TypeOf((*MockQuerier)(nil).DeleteProject), ctx, id) } -// DeleteUnusedVolumes mocks base method. -func (m *MockQuerier) DeleteUnusedVolumes(ctx context.Context, arg DeleteUnusedVolumesParams) error { +// DeleteUnusedKubernetesVolumes mocks base method. +func (m *MockQuerier) DeleteUnusedKubernetesVolumes(ctx context.Context, arg DeleteUnusedKubernetesVolumesParams) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteUnusedVolumes", ctx, arg) + ret := m.ctrl.Call(m, "DeleteUnusedKubernetesVolumes", ctx, arg) ret0, _ := ret[0].(error) return ret0 } -// DeleteUnusedVolumes indicates an expected call of DeleteUnusedVolumes. -func (mr *MockQuerierMockRecorder) DeleteUnusedVolumes(ctx, arg any) *gomock.Call { +// DeleteUnusedKubernetesVolumes indicates an expected call of DeleteUnusedKubernetesVolumes. +func (mr *MockQuerierMockRecorder) DeleteUnusedKubernetesVolumes(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUnusedVolumes", reflect.TypeOf((*MockQuerier)(nil).DeleteUnusedVolumes), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUnusedKubernetesVolumes", reflect.TypeOf((*MockQuerier)(nil).DeleteUnusedKubernetesVolumes), ctx, arg) } // GetApiKeyExistance mocks base method. @@ -186,154 +186,154 @@ func (mr *MockQuerierMockRecorder) GetApiKeyExistance(ctx, apiKey any) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetApiKeyExistance", reflect.TypeOf((*MockQuerier)(nil).GetApiKeyExistance), ctx, apiKey) } -// GetProject mocks base method. -func (m *MockQuerier) GetProject(ctx context.Context, id uuid.UUID) (Project, error) { +// GetKubernetesProjectBranches mocks base method. +func (m *MockQuerier) GetKubernetesProjectBranches(ctx context.Context, projectID uuid.UUID) ([]string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetProject", ctx, id) - ret0, _ := ret[0].(Project) + ret := m.ctrl.Call(m, "GetKubernetesProjectBranches", ctx, projectID) + ret0, _ := ret[0].([]string) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetProject indicates an expected call of GetProject. -func (mr *MockQuerierMockRecorder) GetProject(ctx, id any) *gomock.Call { +// GetKubernetesProjectBranches indicates an expected call of GetKubernetesProjectBranches. +func (mr *MockQuerierMockRecorder) GetKubernetesProjectBranches(ctx, projectID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProject", reflect.TypeOf((*MockQuerier)(nil).GetProject), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKubernetesProjectBranches", reflect.TypeOf((*MockQuerier)(nil).GetKubernetesProjectBranches), ctx, projectID) } -// GetProjectBranches mocks base method. -func (m *MockQuerier) GetProjectBranches(ctx context.Context, projectID uuid.UUID) ([]string, error) { +// GetKubernetesServiceByName mocks base method. +func (m *MockQuerier) GetKubernetesServiceByName(ctx context.Context, arg GetKubernetesServiceByNameParams) (KubernetesService, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetProjectBranches", ctx, projectID) - ret0, _ := ret[0].([]string) + ret := m.ctrl.Call(m, "GetKubernetesServiceByName", ctx, arg) + ret0, _ := ret[0].(KubernetesService) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetProjectBranches indicates an expected call of GetProjectBranches. -func (mr *MockQuerierMockRecorder) GetProjectBranches(ctx, projectID any) *gomock.Call { +// GetKubernetesServiceByName indicates an expected call of GetKubernetesServiceByName. +func (mr *MockQuerierMockRecorder) GetKubernetesServiceByName(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectBranches", reflect.TypeOf((*MockQuerier)(nil).GetProjectBranches), ctx, projectID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKubernetesServiceByName", reflect.TypeOf((*MockQuerier)(nil).GetKubernetesServiceByName), ctx, arg) } -// GetProjectById mocks base method. -func (m *MockQuerier) GetProjectById(ctx context.Context, id uuid.UUID) (Project, error) { +// GetKubernetesServicesByProject mocks base method. +func (m *MockQuerier) GetKubernetesServicesByProject(ctx context.Context, arg GetKubernetesServicesByProjectParams) ([]KubernetesService, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetProjectById", ctx, id) - ret0, _ := ret[0].(Project) + ret := m.ctrl.Call(m, "GetKubernetesServicesByProject", ctx, arg) + ret0, _ := ret[0].([]KubernetesService) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetProjectById indicates an expected call of GetProjectById. -func (mr *MockQuerierMockRecorder) GetProjectById(ctx, id any) *gomock.Call { +// GetKubernetesServicesByProject indicates an expected call of GetKubernetesServicesByProject. +func (mr *MockQuerierMockRecorder) GetKubernetesServicesByProject(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectById", reflect.TypeOf((*MockQuerier)(nil).GetProjectById), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKubernetesServicesByProject", reflect.TypeOf((*MockQuerier)(nil).GetKubernetesServicesByProject), ctx, arg) } -// GetProjectByName mocks base method. -func (m *MockQuerier) GetProjectByName(ctx context.Context, name string) (Project, error) { +// GetKubernetesServicesByUser mocks base method. +func (m *MockQuerier) GetKubernetesServicesByUser(ctx context.Context, userID uuid.UUID) ([]GetKubernetesServicesByUserRow, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetProjectByName", ctx, name) - ret0, _ := ret[0].(Project) + ret := m.ctrl.Call(m, "GetKubernetesServicesByUser", ctx, userID) + ret0, _ := ret[0].([]GetKubernetesServicesByUserRow) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetProjectByName indicates an expected call of GetProjectByName. -func (mr *MockQuerierMockRecorder) GetProjectByName(ctx, name any) *gomock.Call { +// GetKubernetesServicesByUser indicates an expected call of GetKubernetesServicesByUser. +func (mr *MockQuerierMockRecorder) GetKubernetesServicesByUser(ctx, userID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectByName", reflect.TypeOf((*MockQuerier)(nil).GetProjectByName), ctx, name) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKubernetesServicesByUser", reflect.TypeOf((*MockQuerier)(nil).GetKubernetesServicesByUser), ctx, userID) } -// GetProjectsByUser mocks base method. -func (m *MockQuerier) GetProjectsByUser(ctx context.Context, userID uuid.UUID) ([]Project, error) { +// GetKubernetesVolumeIdentifier mocks base method. +func (m *MockQuerier) GetKubernetesVolumeIdentifier(ctx context.Context, arg GetKubernetesVolumeIdentifierParams) (uuid.UUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetProjectsByUser", ctx, userID) - ret0, _ := ret[0].([]Project) + ret := m.ctrl.Call(m, "GetKubernetesVolumeIdentifier", ctx, arg) + ret0, _ := ret[0].(uuid.UUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetProjectsByUser indicates an expected call of GetProjectsByUser. -func (mr *MockQuerierMockRecorder) GetProjectsByUser(ctx, userID any) *gomock.Call { +// GetKubernetesVolumeIdentifier indicates an expected call of GetKubernetesVolumeIdentifier. +func (mr *MockQuerierMockRecorder) GetKubernetesVolumeIdentifier(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectsByUser", reflect.TypeOf((*MockQuerier)(nil).GetProjectsByUser), ctx, userID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKubernetesVolumeIdentifier", reflect.TypeOf((*MockQuerier)(nil).GetKubernetesVolumeIdentifier), ctx, arg) } -// GetService mocks base method. -func (m *MockQuerier) GetService(ctx context.Context, id uuid.UUID) (Service, error) { +// GetProject mocks base method. +func (m *MockQuerier) GetProject(ctx context.Context, id uuid.UUID) (Project, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetService", ctx, id) - ret0, _ := ret[0].(Service) + ret := m.ctrl.Call(m, "GetProject", ctx, id) + ret0, _ := ret[0].(Project) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetService indicates an expected call of GetService. -func (mr *MockQuerierMockRecorder) GetService(ctx, id any) *gomock.Call { +// GetProject indicates an expected call of GetProject. +func (mr *MockQuerierMockRecorder) GetProject(ctx, id any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetService", reflect.TypeOf((*MockQuerier)(nil).GetService), ctx, id) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProject", reflect.TypeOf((*MockQuerier)(nil).GetProject), ctx, id) } -// GetServiceByName mocks base method. -func (m *MockQuerier) GetServiceByName(ctx context.Context, arg GetServiceByNameParams) (Service, error) { +// GetProjectById mocks base method. +func (m *MockQuerier) GetProjectById(ctx context.Context, id uuid.UUID) (Project, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetServiceByName", ctx, arg) - ret0, _ := ret[0].(Service) + ret := m.ctrl.Call(m, "GetProjectById", ctx, id) + ret0, _ := ret[0].(Project) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetServiceByName indicates an expected call of GetServiceByName. -func (mr *MockQuerierMockRecorder) GetServiceByName(ctx, arg any) *gomock.Call { +// GetProjectById indicates an expected call of GetProjectById. +func (mr *MockQuerierMockRecorder) GetProjectById(ctx, id any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceByName", reflect.TypeOf((*MockQuerier)(nil).GetServiceByName), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectById", reflect.TypeOf((*MockQuerier)(nil).GetProjectById), ctx, id) } -// GetServicesByProject mocks base method. -func (m *MockQuerier) GetServicesByProject(ctx context.Context, arg GetServicesByProjectParams) ([]Service, error) { +// GetProjectByName mocks base method. +func (m *MockQuerier) GetProjectByName(ctx context.Context, name string) (Project, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetServicesByProject", ctx, arg) - ret0, _ := ret[0].([]Service) + ret := m.ctrl.Call(m, "GetProjectByName", ctx, name) + ret0, _ := ret[0].(Project) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetServicesByProject indicates an expected call of GetServicesByProject. -func (mr *MockQuerierMockRecorder) GetServicesByProject(ctx, arg any) *gomock.Call { +// GetProjectByName indicates an expected call of GetProjectByName. +func (mr *MockQuerierMockRecorder) GetProjectByName(ctx, name any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServicesByProject", reflect.TypeOf((*MockQuerier)(nil).GetServicesByProject), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectByName", reflect.TypeOf((*MockQuerier)(nil).GetProjectByName), ctx, name) } -// GetServicesByUser mocks base method. -func (m *MockQuerier) GetServicesByUser(ctx context.Context, userID uuid.UUID) ([]GetServicesByUserRow, error) { +// GetProjectsByUser mocks base method. +func (m *MockQuerier) GetProjectsByUser(ctx context.Context, userID uuid.UUID) ([]Project, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetServicesByUser", ctx, userID) - ret0, _ := ret[0].([]GetServicesByUserRow) + ret := m.ctrl.Call(m, "GetProjectsByUser", ctx, userID) + ret0, _ := ret[0].([]Project) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetServicesByUser indicates an expected call of GetServicesByUser. -func (mr *MockQuerierMockRecorder) GetServicesByUser(ctx, userID any) *gomock.Call { +// GetProjectsByUser indicates an expected call of GetProjectsByUser. +func (mr *MockQuerierMockRecorder) GetProjectsByUser(ctx, userID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServicesByUser", reflect.TypeOf((*MockQuerier)(nil).GetServicesByUser), ctx, userID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjectsByUser", reflect.TypeOf((*MockQuerier)(nil).GetProjectsByUser), ctx, userID) } -// GetUnusedVolumeIdentifiers mocks base method. -func (m *MockQuerier) GetUnusedVolumeIdentifiers(ctx context.Context, arg GetUnusedVolumeIdentifiersParams) ([]uuid.UUID, error) { +// GetUnusedKubernetesVolumeIdentifiers mocks base method. +func (m *MockQuerier) GetUnusedKubernetesVolumeIdentifiers(ctx context.Context, arg GetUnusedKubernetesVolumeIdentifiersParams) ([]uuid.UUID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUnusedVolumeIdentifiers", ctx, arg) + ret := m.ctrl.Call(m, "GetUnusedKubernetesVolumeIdentifiers", ctx, arg) ret0, _ := ret[0].([]uuid.UUID) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetUnusedVolumeIdentifiers indicates an expected call of GetUnusedVolumeIdentifiers. -func (mr *MockQuerierMockRecorder) GetUnusedVolumeIdentifiers(ctx, arg any) *gomock.Call { +// GetUnusedKubernetesVolumeIdentifiers indicates an expected call of GetUnusedKubernetesVolumeIdentifiers. +func (mr *MockQuerierMockRecorder) GetUnusedKubernetesVolumeIdentifiers(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUnusedVolumeIdentifiers", reflect.TypeOf((*MockQuerier)(nil).GetUnusedVolumeIdentifiers), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUnusedKubernetesVolumeIdentifiers", reflect.TypeOf((*MockQuerier)(nil).GetUnusedKubernetesVolumeIdentifiers), ctx, arg) } // GetUserByApiKey mocks base method. @@ -351,21 +351,6 @@ func (mr *MockQuerierMockRecorder) GetUserByApiKey(ctx, apiKey any) *gomock.Call return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByApiKey", reflect.TypeOf((*MockQuerier)(nil).GetUserByApiKey), ctx, apiKey) } -// GetVolumeIdentifier mocks base method. -func (m *MockQuerier) GetVolumeIdentifier(ctx context.Context, arg GetVolumeIdentifierParams) (uuid.UUID, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetVolumeIdentifier", ctx, arg) - ret0, _ := ret[0].(uuid.UUID) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetVolumeIdentifier indicates an expected call of GetVolumeIdentifier. -func (mr *MockQuerierMockRecorder) GetVolumeIdentifier(ctx, arg any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVolumeIdentifier", reflect.TypeOf((*MockQuerier)(nil).GetVolumeIdentifier), ctx, arg) -} - // IsUserInProject mocks base method. func (m *MockQuerier) IsUserInProject(ctx context.Context, arg IsUserInProjectParams) (bool, error) { m.ctrl.T.Helper() @@ -381,30 +366,30 @@ func (mr *MockQuerierMockRecorder) IsUserInProject(ctx, arg any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsUserInProject", reflect.TypeOf((*MockQuerier)(nil).IsUserInProject), ctx, arg) } -// SetServiceIngress mocks base method. -func (m *MockQuerier) SetServiceIngress(ctx context.Context, arg SetServiceIngressParams) error { +// SetKubernetesServiceIngress mocks base method. +func (m *MockQuerier) SetKubernetesServiceIngress(ctx context.Context, arg SetKubernetesServiceIngressParams) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetServiceIngress", ctx, arg) + ret := m.ctrl.Call(m, "SetKubernetesServiceIngress", ctx, arg) ret0, _ := ret[0].(error) return ret0 } -// SetServiceIngress indicates an expected call of SetServiceIngress. -func (mr *MockQuerierMockRecorder) SetServiceIngress(ctx, arg any) *gomock.Call { +// SetKubernetesServiceIngress indicates an expected call of SetKubernetesServiceIngress. +func (mr *MockQuerierMockRecorder) SetKubernetesServiceIngress(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetServiceIngress", reflect.TypeOf((*MockQuerier)(nil).SetServiceIngress), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetKubernetesServiceIngress", reflect.TypeOf((*MockQuerier)(nil).SetKubernetesServiceIngress), ctx, arg) } -// SetServiceNodePorts mocks base method. -func (m *MockQuerier) SetServiceNodePorts(ctx context.Context, arg SetServiceNodePortsParams) error { +// SetKubernetesServiceNodePorts mocks base method. +func (m *MockQuerier) SetKubernetesServiceNodePorts(ctx context.Context, arg SetKubernetesServiceNodePortsParams) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetServiceNodePorts", ctx, arg) + ret := m.ctrl.Call(m, "SetKubernetesServiceNodePorts", ctx, arg) ret0, _ := ret[0].(error) return ret0 } -// SetServiceNodePorts indicates an expected call of SetServiceNodePorts. -func (mr *MockQuerierMockRecorder) SetServiceNodePorts(ctx, arg any) *gomock.Call { +// SetKubernetesServiceNodePorts indicates an expected call of SetKubernetesServiceNodePorts. +func (mr *MockQuerierMockRecorder) SetKubernetesServiceNodePorts(ctx, arg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetServiceNodePorts", reflect.TypeOf((*MockQuerier)(nil).SetServiceNodePorts), ctx, arg) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetKubernetesServiceNodePorts", reflect.TypeOf((*MockQuerier)(nil).SetKubernetesServiceNodePorts), ctx, arg) } diff --git a/internal/database/query.sql.go b/internal/database/query.sql.go index aedbeea..4de5cdb 100644 --- a/internal/database/query.sql.go +++ b/internal/database/query.sql.go @@ -46,33 +46,14 @@ func (q *Queries) CheckProjectsTableExists(ctx context.Context) (bool, error) { return exists, err } -const createProject = `-- name: CreateProject :one -INSERT INTO projects (id, name) - VALUES ($1, $2) -RETURNING - id, name -` - -type CreateProjectParams struct { - ID uuid.UUID - Name string -} - -func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) { - row := q.db.QueryRow(ctx, createProject, arg.ID, arg.Name) - var i Project - err := row.Scan(&i.ID, &i.Name) - return i, err -} - -const createService = `-- name: CreateService :one -INSERT INTO services (id, project_id, project_branch, service_name, node_ports, ingress) +const createKubernetesService = `-- name: CreateKubernetesService :one +INSERT INTO kubernetes_services (id, project_id, project_branch, service_name, node_ports, ingress) VALUES ($1, $2, $3, $4, $5, $6) RETURNING - id, project_id, project_branch, service_name, node_ports, ingress + id, project_id, project_branch, service_name, runtime, node_ports, ingress ` -type CreateServiceParams struct { +type CreateKubernetesServiceParams struct { ID uuid.UUID ProjectID uuid.UUID ProjectBranch string @@ -81,8 +62,8 @@ type CreateServiceParams struct { Ingress pgtype.Text } -func (q *Queries) CreateService(ctx context.Context, arg CreateServiceParams) (Service, error) { - row := q.db.QueryRow(ctx, createService, +func (q *Queries) CreateKubernetesService(ctx context.Context, arg CreateKubernetesServiceParams) (KubernetesService, error) { + row := q.db.QueryRow(ctx, createKubernetesService, arg.ID, arg.ProjectID, arg.ProjectBranch, @@ -90,26 +71,27 @@ func (q *Queries) CreateService(ctx context.Context, arg CreateServiceParams) (S arg.NodePorts, arg.Ingress, ) - var i Service + var i KubernetesService err := row.Scan( &i.ID, &i.ProjectID, &i.ProjectBranch, &i.ServiceName, + &i.Runtime, &i.NodePorts, &i.Ingress, ) return i, err } -const createVolume = `-- name: CreateVolume :one +const createKubernetesVolume = `-- name: CreateKubernetesVolume :one INSERT INTO volumes (identifier, volume_name, project_id, project_branch, size) VALUES ($1, $2, $3, $4, $5) RETURNING - identifier, volume_name, project_id, project_branch, size + identifier, runtime, volume_name, project_id, project_branch, size ` -type CreateVolumeParams struct { +type CreateKubernetesVolumeParams struct { Identifier uuid.UUID VolumeName string ProjectID uuid.UUID @@ -117,8 +99,8 @@ type CreateVolumeParams struct { Size int32 } -func (q *Queries) CreateVolume(ctx context.Context, arg CreateVolumeParams) (Volume, error) { - row := q.db.QueryRow(ctx, createVolume, +func (q *Queries) CreateKubernetesVolume(ctx context.Context, arg CreateKubernetesVolumeParams) (Volume, error) { + row := q.db.QueryRow(ctx, createKubernetesVolume, arg.Identifier, arg.VolumeName, arg.ProjectID, @@ -128,6 +110,7 @@ func (q *Queries) CreateVolume(ctx context.Context, arg CreateVolumeParams) (Vol var i Volume err := row.Scan( &i.Identifier, + &i.Runtime, &i.VolumeName, &i.ProjectID, &i.ProjectBranch, @@ -136,59 +119,78 @@ func (q *Queries) CreateVolume(ctx context.Context, arg CreateVolumeParams) (Vol return i, err } -const deleteProject = `-- name: DeleteProject :exec -DELETE FROM projects -WHERE id = $1 +const createProject = `-- name: CreateProject :one +INSERT INTO projects (id, name) + VALUES ($1, $2) +RETURNING + id, name ` -func (q *Queries) DeleteProject(ctx context.Context, id uuid.UUID) error { - _, err := q.db.Exec(ctx, deleteProject, id) - return err +type CreateProjectParams struct { + ID uuid.UUID + Name string +} + +func (q *Queries) CreateProject(ctx context.Context, arg CreateProjectParams) (Project, error) { + row := q.db.QueryRow(ctx, createProject, arg.ID, arg.Name) + var i Project + err := row.Scan(&i.ID, &i.Name) + return i, err } -const deleteServiceById = `-- name: DeleteServiceById :exec -DELETE FROM services +const deleteKubernetesServiceById = `-- name: DeleteKubernetesServiceById :exec +DELETE FROM kubernetes_services WHERE id = $1 ` -func (q *Queries) DeleteServiceById(ctx context.Context, id uuid.UUID) error { - _, err := q.db.Exec(ctx, deleteServiceById, id) +func (q *Queries) DeleteKubernetesServiceById(ctx context.Context, id uuid.UUID) error { + _, err := q.db.Exec(ctx, deleteKubernetesServiceById, id) return err } -const deleteServiceByName = `-- name: DeleteServiceByName :exec -DELETE FROM services +const deleteKubernetesServiceByName = `-- name: DeleteKubernetesServiceByName :exec +DELETE FROM kubernetes_services WHERE service_name = $1 AND project_id = $2 AND project_branch = $3 ` -type DeleteServiceByNameParams struct { +type DeleteKubernetesServiceByNameParams struct { ServiceName string ProjectID uuid.UUID ProjectBranch string } -func (q *Queries) DeleteServiceByName(ctx context.Context, arg DeleteServiceByNameParams) error { - _, err := q.db.Exec(ctx, deleteServiceByName, arg.ServiceName, arg.ProjectID, arg.ProjectBranch) +func (q *Queries) DeleteKubernetesServiceByName(ctx context.Context, arg DeleteKubernetesServiceByNameParams) error { + _, err := q.db.Exec(ctx, deleteKubernetesServiceByName, arg.ServiceName, arg.ProjectID, arg.ProjectBranch) return err } -const deleteUnusedVolumes = `-- name: DeleteUnusedVolumes :exec -DELETE FROM volumes +const deleteProject = `-- name: DeleteProject :exec +DELETE FROM projects +WHERE id = $1 +` + +func (q *Queries) DeleteProject(ctx context.Context, id uuid.UUID) error { + _, err := q.db.Exec(ctx, deleteProject, id) + return err +} + +const deleteUnusedKubernetesVolumes = `-- name: DeleteUnusedKubernetesVolumes :exec +DELETE FROM kubernetes_volumes WHERE project_id = $1 AND project_branch = $2 AND NOT volume_name = ANY ($3::text[]) ` -type DeleteUnusedVolumesParams struct { +type DeleteUnusedKubernetesVolumesParams struct { ProjectID uuid.UUID ProjectBranch string ExcludeVolumes []string } -func (q *Queries) DeleteUnusedVolumes(ctx context.Context, arg DeleteUnusedVolumesParams) error { - _, err := q.db.Exec(ctx, deleteUnusedVolumes, arg.ProjectID, arg.ProjectBranch, arg.ExcludeVolumes) +func (q *Queries) DeleteUnusedKubernetesVolumes(ctx context.Context, arg DeleteUnusedKubernetesVolumesParams) error { + _, err := q.db.Exec(ctx, deleteUnusedKubernetesVolumes, arg.ProjectID, arg.ProjectBranch, arg.ExcludeVolumes) return err } @@ -210,28 +212,11 @@ func (q *Queries) GetApiKeyExistance(ctx context.Context, apiKey string) (bool, return exists, err } -const getProject = `-- name: GetProject :one -SELECT - id, name -FROM - projects -WHERE - id = $1 -LIMIT 1 -` - -func (q *Queries) GetProject(ctx context.Context, id uuid.UUID) (Project, error) { - row := q.db.QueryRow(ctx, getProject, id) - var i Project - err := row.Scan(&i.ID, &i.Name) - return i, err -} - -const getProjectBranches = `-- name: GetProjectBranches :many +const getKubernetesProjectBranches = `-- name: GetKubernetesProjectBranches :many SELECT project_branch FROM - services s + kubernetes_services s WHERE s.project_id = $1 UNION @@ -243,8 +228,8 @@ WHERE v.project_id = $1 ` -func (q *Queries) GetProjectBranches(ctx context.Context, projectID uuid.UUID) ([]string, error) { - rows, err := q.db.Query(ctx, getProjectBranches, projectID) +func (q *Queries) GetKubernetesProjectBranches(ctx context.Context, projectID uuid.UUID) ([]string, error) { + rows, err := q.db.Query(ctx, getKubernetesProjectBranches, projectID) if err != nil { return nil, err } @@ -263,101 +248,11 @@ func (q *Queries) GetProjectBranches(ctx context.Context, projectID uuid.UUID) ( return items, nil } -const getProjectById = `-- name: GetProjectById :one -SELECT - id, - name -FROM - projects -WHERE - id = $1 -` - -func (q *Queries) GetProjectById(ctx context.Context, id uuid.UUID) (Project, error) { - row := q.db.QueryRow(ctx, getProjectById, id) - var i Project - err := row.Scan(&i.ID, &i.Name) - return i, err -} - -const getProjectByName = `-- name: GetProjectByName :one -SELECT - id, name -FROM - projects -WHERE - name = $1 -LIMIT 1 -` - -func (q *Queries) GetProjectByName(ctx context.Context, name string) (Project, error) { - row := q.db.QueryRow(ctx, getProjectByName, name) - var i Project - err := row.Scan(&i.ID, &i.Name) - return i, err -} - -const getProjectsByUser = `-- name: GetProjectsByUser :many -SELECT - p.id, p.name -FROM - projects p - JOIN user_projects up ON p.id = up.project_id -WHERE - up.user_id = $1 -ORDER BY - p.name -` - -func (q *Queries) GetProjectsByUser(ctx context.Context, userID uuid.UUID) ([]Project, error) { - rows, err := q.db.Query(ctx, getProjectsByUser, userID) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Project - for rows.Next() { - var i Project - if err := rows.Scan(&i.ID, &i.Name); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getService = `-- name: GetService :one -SELECT - id, project_id, project_branch, service_name, node_ports, ingress -FROM - services -WHERE - id = $1 -LIMIT 1 -` - -func (q *Queries) GetService(ctx context.Context, id uuid.UUID) (Service, error) { - row := q.db.QueryRow(ctx, getService, id) - var i Service - err := row.Scan( - &i.ID, - &i.ProjectID, - &i.ProjectBranch, - &i.ServiceName, - &i.NodePorts, - &i.Ingress, - ) - return i, err -} - -const getServiceByName = `-- name: GetServiceByName :one +const getKubernetesServiceByName = `-- name: GetKubernetesServiceByName :one SELECT - id, project_id, project_branch, service_name, node_ports, ingress + id, project_id, project_branch, service_name, runtime, node_ports, ingress FROM - services + kubernetes_services WHERE service_name = $1 AND project_id = $2 @@ -365,31 +260,32 @@ WHERE LIMIT 1 ` -type GetServiceByNameParams struct { +type GetKubernetesServiceByNameParams struct { ServiceName string ProjectID uuid.UUID ProjectBranch string } -func (q *Queries) GetServiceByName(ctx context.Context, arg GetServiceByNameParams) (Service, error) { - row := q.db.QueryRow(ctx, getServiceByName, arg.ServiceName, arg.ProjectID, arg.ProjectBranch) - var i Service +func (q *Queries) GetKubernetesServiceByName(ctx context.Context, arg GetKubernetesServiceByNameParams) (KubernetesService, error) { + row := q.db.QueryRow(ctx, getKubernetesServiceByName, arg.ServiceName, arg.ProjectID, arg.ProjectBranch) + var i KubernetesService err := row.Scan( &i.ID, &i.ProjectID, &i.ProjectBranch, &i.ServiceName, + &i.Runtime, &i.NodePorts, &i.Ingress, ) return i, err } -const getServicesByProject = `-- name: GetServicesByProject :many +const getKubernetesServicesByProject = `-- name: GetKubernetesServicesByProject :many SELECT - id, project_id, project_branch, service_name, node_ports, ingress + id, project_id, project_branch, service_name, runtime, node_ports, ingress FROM - services + kubernetes_services WHERE project_id = $1 AND project_branch = $2 @@ -397,25 +293,26 @@ ORDER BY service_name ` -type GetServicesByProjectParams struct { +type GetKubernetesServicesByProjectParams struct { ProjectID uuid.UUID ProjectBranch string } -func (q *Queries) GetServicesByProject(ctx context.Context, arg GetServicesByProjectParams) ([]Service, error) { - rows, err := q.db.Query(ctx, getServicesByProject, arg.ProjectID, arg.ProjectBranch) +func (q *Queries) GetKubernetesServicesByProject(ctx context.Context, arg GetKubernetesServicesByProjectParams) ([]KubernetesService, error) { + rows, err := q.db.Query(ctx, getKubernetesServicesByProject, arg.ProjectID, arg.ProjectBranch) if err != nil { return nil, err } defer rows.Close() - var items []Service + var items []KubernetesService for rows.Next() { - var i Service + var i KubernetesService if err := rows.Scan( &i.ID, &i.ProjectID, &i.ProjectBranch, &i.ServiceName, + &i.Runtime, &i.NodePorts, &i.Ingress, ); err != nil { @@ -429,12 +326,12 @@ func (q *Queries) GetServicesByProject(ctx context.Context, arg GetServicesByPro return items, nil } -const getServicesByUser = `-- name: GetServicesByUser :many +const getKubernetesServicesByUser = `-- name: GetKubernetesServicesByUser :many SELECT - s.id, s.project_id, s.project_branch, s.service_name, s.node_ports, s.ingress, + s.id, s.project_id, s.project_branch, s.service_name, s.runtime, s.node_ports, s.ingress, p.name AS project_name FROM - services s + kubernetes_services s JOIN projects p ON s.project_id = p.id JOIN user_projects up ON up.project_id = p.id WHERE @@ -444,30 +341,32 @@ ORDER BY s.service_name ` -type GetServicesByUserRow struct { +type GetKubernetesServicesByUserRow struct { ID uuid.UUID ProjectID uuid.UUID ProjectBranch string ServiceName string + Runtime Runtime NodePorts []int32 Ingress pgtype.Text ProjectName string } -func (q *Queries) GetServicesByUser(ctx context.Context, userID uuid.UUID) ([]GetServicesByUserRow, error) { - rows, err := q.db.Query(ctx, getServicesByUser, userID) +func (q *Queries) GetKubernetesServicesByUser(ctx context.Context, userID uuid.UUID) ([]GetKubernetesServicesByUserRow, error) { + rows, err := q.db.Query(ctx, getKubernetesServicesByUser, userID) if err != nil { return nil, err } defer rows.Close() - var items []GetServicesByUserRow + var items []GetKubernetesServicesByUserRow for rows.Next() { - var i GetServicesByUserRow + var i GetKubernetesServicesByUserRow if err := rows.Scan( &i.ID, &i.ProjectID, &i.ProjectBranch, &i.ServiceName, + &i.Runtime, &i.NodePorts, &i.Ingress, &i.ProjectName, @@ -482,25 +381,132 @@ func (q *Queries) GetServicesByUser(ctx context.Context, userID uuid.UUID) ([]Ge return items, nil } -const getUnusedVolumeIdentifiers = `-- name: GetUnusedVolumeIdentifiers :many +const getKubernetesVolumeIdentifier = `-- name: GetKubernetesVolumeIdentifier :one +SELECT + identifier +FROM + kubernetes_volumes +WHERE + volume_name = $1 + AND project_id = $2 + AND project_branch = $3 +` + +type GetKubernetesVolumeIdentifierParams struct { + VolumeName string + ProjectID uuid.UUID + ProjectBranch string +} + +func (q *Queries) GetKubernetesVolumeIdentifier(ctx context.Context, arg GetKubernetesVolumeIdentifierParams) (uuid.UUID, error) { + row := q.db.QueryRow(ctx, getKubernetesVolumeIdentifier, arg.VolumeName, arg.ProjectID, arg.ProjectBranch) + var identifier uuid.UUID + err := row.Scan(&identifier) + return identifier, err +} + +const getProject = `-- name: GetProject :one +SELECT + id, name +FROM + projects +WHERE + id = $1 +LIMIT 1 +` + +func (q *Queries) GetProject(ctx context.Context, id uuid.UUID) (Project, error) { + row := q.db.QueryRow(ctx, getProject, id) + var i Project + err := row.Scan(&i.ID, &i.Name) + return i, err +} + +const getProjectById = `-- name: GetProjectById :one +SELECT + id, + name +FROM + projects +WHERE + id = $1 +` + +func (q *Queries) GetProjectById(ctx context.Context, id uuid.UUID) (Project, error) { + row := q.db.QueryRow(ctx, getProjectById, id) + var i Project + err := row.Scan(&i.ID, &i.Name) + return i, err +} + +const getProjectByName = `-- name: GetProjectByName :one +SELECT + id, name +FROM + projects +WHERE + name = $1 +LIMIT 1 +` + +func (q *Queries) GetProjectByName(ctx context.Context, name string) (Project, error) { + row := q.db.QueryRow(ctx, getProjectByName, name) + var i Project + err := row.Scan(&i.ID, &i.Name) + return i, err +} + +const getProjectsByUser = `-- name: GetProjectsByUser :many +SELECT + p.id, p.name +FROM + projects p + JOIN user_projects up ON p.id = up.project_id +WHERE + up.user_id = $1 +ORDER BY + p.name +` + +func (q *Queries) GetProjectsByUser(ctx context.Context, userID uuid.UUID) ([]Project, error) { + rows, err := q.db.Query(ctx, getProjectsByUser, userID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Project + for rows.Next() { + var i Project + if err := rows.Scan(&i.ID, &i.Name); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getUnusedKubernetesVolumeIdentifiers = `-- name: GetUnusedKubernetesVolumeIdentifiers :many SELECT identifier FROM - volumes + kubernetes_volumes WHERE project_id = $1 AND project_branch = $2 AND NOT volume_name = ANY ($3::text[]) ` -type GetUnusedVolumeIdentifiersParams struct { +type GetUnusedKubernetesVolumeIdentifiersParams struct { ProjectID uuid.UUID ProjectBranch string ExcludeVolumes []string } -func (q *Queries) GetUnusedVolumeIdentifiers(ctx context.Context, arg GetUnusedVolumeIdentifiersParams) ([]uuid.UUID, error) { - rows, err := q.db.Query(ctx, getUnusedVolumeIdentifiers, arg.ProjectID, arg.ProjectBranch, arg.ExcludeVolumes) +func (q *Queries) GetUnusedKubernetesVolumeIdentifiers(ctx context.Context, arg GetUnusedKubernetesVolumeIdentifiersParams) ([]uuid.UUID, error) { + rows, err := q.db.Query(ctx, getUnusedKubernetesVolumeIdentifiers, arg.ProjectID, arg.ProjectBranch, arg.ExcludeVolumes) if err != nil { return nil, err } @@ -536,30 +542,6 @@ func (q *Queries) GetUserByApiKey(ctx context.Context, apiKey string) (User, err return i, err } -const getVolumeIdentifier = `-- name: GetVolumeIdentifier :one -SELECT - identifier -FROM - volumes -WHERE - volume_name = $1 - AND project_id = $2 - AND project_branch = $3 -` - -type GetVolumeIdentifierParams struct { - VolumeName string - ProjectID uuid.UUID - ProjectBranch string -} - -func (q *Queries) GetVolumeIdentifier(ctx context.Context, arg GetVolumeIdentifierParams) (uuid.UUID, error) { - row := q.db.QueryRow(ctx, getVolumeIdentifier, arg.VolumeName, arg.ProjectID, arg.ProjectBranch) - var identifier uuid.UUID - err := row.Scan(&identifier) - return identifier, err -} - const isUserInProject = `-- name: IsUserInProject :one SELECT EXISTS ( @@ -584,44 +566,44 @@ func (q *Queries) IsUserInProject(ctx context.Context, arg IsUserInProjectParams return exists, err } -const setServiceIngress = `-- name: SetServiceIngress :exec +const setKubernetesServiceIngress = `-- name: SetKubernetesServiceIngress :exec UPDATE - services + kubernetes_services SET ingress = $2 WHERE id = $1 RETURNING - id, project_id, project_branch, service_name, node_ports, ingress + id, project_id, project_branch, service_name, runtime, node_ports, ingress ` -type SetServiceIngressParams struct { +type SetKubernetesServiceIngressParams struct { ID uuid.UUID Ingress pgtype.Text } -func (q *Queries) SetServiceIngress(ctx context.Context, arg SetServiceIngressParams) error { - _, err := q.db.Exec(ctx, setServiceIngress, arg.ID, arg.Ingress) +func (q *Queries) SetKubernetesServiceIngress(ctx context.Context, arg SetKubernetesServiceIngressParams) error { + _, err := q.db.Exec(ctx, setKubernetesServiceIngress, arg.ID, arg.Ingress) return err } -const setServiceNodePorts = `-- name: SetServiceNodePorts :exec +const setKubernetesServiceNodePorts = `-- name: SetKubernetesServiceNodePorts :exec UPDATE - services + kubernetes_services SET node_ports = $2 WHERE id = $1 RETURNING - id, project_id, project_branch, service_name, node_ports, ingress + id, project_id, project_branch, service_name, runtime, node_ports, ingress ` -type SetServiceNodePortsParams struct { +type SetKubernetesServiceNodePortsParams struct { ID uuid.UUID NodePorts []int32 } -func (q *Queries) SetServiceNodePorts(ctx context.Context, arg SetServiceNodePortsParams) error { - _, err := q.db.Exec(ctx, setServiceNodePorts, arg.ID, arg.NodePorts) +func (q *Queries) SetKubernetesServiceNodePorts(ctx context.Context, arg SetKubernetesServiceNodePortsParams) error { + _, err := q.db.Exec(ctx, setKubernetesServiceNodePorts, arg.ID, arg.NodePorts) return err } diff --git a/internal/env/env.go b/internal/env/env.go index 8eb8a98..1ca92b3 100644 --- a/internal/env/env.go +++ b/internal/env/env.go @@ -18,7 +18,7 @@ var envKey envKeyType type Env struct { Logger *slog.Logger Database database.Querier - Config config.Config + Config config.EnvConfig } // Null constructs a null instance. diff --git a/internal/kubernetes/deployments.go b/internal/kubernetes/deployments.go index e88bdb5..5f46b1f 100644 --- a/internal/kubernetes/deployments.go +++ b/internal/kubernetes/deployments.go @@ -6,8 +6,8 @@ import ( "log" "time" + "nimbus/internal/config" nimbusEnv "nimbus/internal/env" - "nimbus/internal/models" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -21,8 +21,8 @@ const ( ) func GenerateDeploymentSpec( - ctx context.Context, deploymentRequest *models.DeployRequest, - service *models.Service, env *nimbusEnv.Env, + ctx context.Context, deploymentRequest *config.DeployRequest, + service *config.Service, env *nimbusEnv.Env, ) (*appsv1.Deployment, error) { var defaultReplicas int32 = 1 spec := appsv1.DeploymentSpec{ @@ -69,7 +69,7 @@ func GenerateDeploymentSpec( service.Version = "13" } if len(service.Volumes) == 0 { - service.Volumes = []models.Volume{{ + service.Volumes = []config.Volume{{ Name: fmt.Sprintf("%s-psql", service.Name), MountPath: "/var/lib/postgresql/data", }} @@ -106,7 +106,7 @@ func GenerateDeploymentSpec( service.Version = "6" } if len(service.Volumes) == 0 { - service.Volumes = []models.Volume{{ + service.Volumes = []config.Volume{{ Name: fmt.Sprintf("%s-redis", service.Name), MountPath: "/data", }} diff --git a/internal/kubernetes/ingress.go b/internal/kubernetes/ingress.go index 786ec47..5ea15bb 100644 --- a/internal/kubernetes/ingress.go +++ b/internal/kubernetes/ingress.go @@ -9,8 +9,8 @@ import ( "os" "time" + "nimbus/internal/config" "nimbus/internal/env" - "nimbus/internal/models" "k8s.io/apimachinery/pkg/api/errors" @@ -18,7 +18,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func GenerateIngressSpec(namespace string, service *models.Service, +func GenerateIngressSpec(namespace string, service *config.Service, existingIngress *string, env *env.Env, ) (*networkingv1.Ingress, error) { if service.Template != "http" || !service.Public { diff --git a/internal/kubernetes/services.go b/internal/kubernetes/services.go index 6cd20b9..2327e81 100644 --- a/internal/kubernetes/services.go +++ b/internal/kubernetes/services.go @@ -6,9 +6,9 @@ import ( "log/slog" "time" + "nimbus/internal/config" "nimbus/internal/database" nimbusEnv "nimbus/internal/env" - "nimbus/internal/models" "k8s.io/apimachinery/pkg/api/errors" @@ -22,7 +22,7 @@ const ( ) func GenerateServiceSpec(namespace string, - newService *models.Service, oldService *database.Service, + newService *config.Service, oldService *database.KubernetesService, ) (*corev1.Service, error) { spec := corev1.ServiceSpec{ Selector: map[string]string{ diff --git a/internal/kubernetes/volumes.go b/internal/kubernetes/volumes.go index 4d2956a..a7f2326 100644 --- a/internal/kubernetes/volumes.go +++ b/internal/kubernetes/volumes.go @@ -7,9 +7,9 @@ import ( "log" "log/slog" + "nimbus/internal/config" "nimbus/internal/database" "nimbus/internal/env" - "nimbus/internal/models" "github.com/google/uuid" "github.com/jackc/pgx/v5" @@ -26,8 +26,8 @@ type VolumeInfo struct { } func GetVolumeIdentifiers( - ctx context.Context, service *models.Service, - deploymentRequest *models.DeployRequest, env *env.Env, + ctx context.Context, service *config.Service, + deploymentRequest *config.DeployRequest, env *env.Env, ) (map[string]VolumeInfo, error) { volumeMap := make(map[string]VolumeInfo) @@ -36,11 +36,12 @@ func GetVolumeIdentifiers( volume.Size = 100 // default to 100Mi } - identifier, err := env.Database.GetVolumeIdentifier(ctx, database.GetVolumeIdentifierParams{ - VolumeName: volume.Name, - ProjectID: deploymentRequest.ProjectID, - ProjectBranch: deploymentRequest.BranchName, - }) + identifier, err := env.Database.GetKubernetesVolumeIdentifier(ctx, + database.GetKubernetesVolumeIdentifierParams{ + VolumeName: volume.Name, + ProjectID: deploymentRequest.ProjectID, + ProjectBranch: deploymentRequest.BranchName, + }) if errors.Is(err, pgx.ErrNoRows) { env.Logger.DebugContext( ctx, "volume identifier does not exist - creating one", @@ -51,13 +52,14 @@ func GetVolumeIdentifiers( if err != nil { return nil, fmt.Errorf("creating pvc: %w", err) } - _, err := env.Database.CreateVolume(ctx, database.CreateVolumeParams{ - Identifier: identifier, - VolumeName: volume.Name, - ProjectID: deploymentRequest.ProjectID, - ProjectBranch: deploymentRequest.BranchName, - Size: volume.Size, - }) + _, err := env.Database.CreateKubernetesVolume(ctx, + database.CreateKubernetesVolumeParams{ + Identifier: identifier, + VolumeName: volume.Name, + ProjectID: deploymentRequest.ProjectID, + ProjectBranch: deploymentRequest.BranchName, + Size: volume.Size, + }) if err != nil { return nil, fmt.Errorf("creating volume in database: %w", err) } diff --git a/internal/setup/setup.go b/internal/setup/setup.go index 7b4e797..e72d7c1 100644 --- a/internal/setup/setup.go +++ b/internal/setup/setup.go @@ -12,7 +12,7 @@ import ( "github.com/jackc/pgx/v5/pgxpool" ) -func Database(ctx context.Context, config config.Config) (*database.Database, error) { +func Database(ctx context.Context, config config.EnvConfig) (*database.Database, error) { poolConfig, err := pgxpool.ParseConfig("") if err != nil { return nil, fmt.Errorf("parsing config: %w", err) diff --git a/internal/sql/query.sql b/internal/sql/query.sql index dd6f33c..7123494 100644 --- a/internal/sql/query.sql +++ b/internal/sql/query.sql @@ -17,45 +17,36 @@ RETURNING DELETE FROM projects WHERE id = $1; --- name: GetService :one +-- name: GetKubernetesServicesByProject :many SELECT * FROM - services -WHERE - id = $1 -LIMIT 1; - --- name: GetServicesByProject :many -SELECT - * -FROM - services + kubernetes_services WHERE project_id = $1 AND project_branch = $2 ORDER BY service_name; --- name: CreateService :one -INSERT INTO services (id, project_id, project_branch, service_name, node_ports, ingress) +-- name: CreateKubernetesService :one +INSERT INTO kubernetes_services (id, project_id, project_branch, service_name, node_ports, ingress) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *; --- name: DeleteServiceByName :exec -DELETE FROM services +-- name: DeleteKubernetesServiceByName :exec +DELETE FROM kubernetes_services WHERE service_name = $1 AND project_id = $2 AND project_branch = $3; --- name: DeleteServiceById :exec -DELETE FROM services +-- name: DeleteKubernetesServiceById :exec +DELETE FROM kubernetes_services WHERE id = $1; --- name: SetServiceNodePorts :exec +-- name: SetKubernetesServiceNodePorts :exec UPDATE - services + kubernetes_services SET node_ports = $2 WHERE @@ -63,9 +54,9 @@ WHERE RETURNING *; --- name: SetServiceIngress :exec +-- name: SetKubernetesServiceIngress :exec UPDATE - services + kubernetes_services SET ingress = $2 WHERE @@ -73,27 +64,27 @@ WHERE RETURNING *; --- name: GetVolumeIdentifier :one +-- name: GetKubernetesVolumeIdentifier :one SELECT identifier FROM - volumes + kubernetes_volumes WHERE volume_name = $1 AND project_id = $2 AND project_branch = $3; --- name: CreateVolume :one +-- name: CreateKubernetesVolume :one INSERT INTO volumes (identifier, volume_name, project_id, project_branch, size) VALUES ($1, $2, $3, $4, $5) RETURNING *; --- name: GetUnusedVolumeIdentifiers :many +-- name: GetUnusedKubernetesVolumeIdentifiers :many SELECT identifier FROM - volumes + kubernetes_volumes WHERE project_id = $1 AND project_branch = $2 @@ -147,8 +138,8 @@ SELECT user_id = $1 AND project_id = $2); --- name: DeleteUnusedVolumes :exec -DELETE FROM volumes +-- name: DeleteUnusedKubernetesVolumes :exec +DELETE FROM kubernetes_volumes WHERE project_id = $1 AND project_branch = $2 AND NOT volume_name = ANY (@exclude_volumes::text[]); @@ -164,12 +155,12 @@ WHERE ORDER BY p.name; --- name: GetServicesByUser :many +-- name: GetKubernetesServicesByUser :many SELECT s.*, p.name AS project_name FROM - services s + kubernetes_services s JOIN projects p ON s.project_id = p.id JOIN user_projects up ON up.project_id = p.id WHERE @@ -178,11 +169,11 @@ ORDER BY p.name, s.service_name; --- name: GetServiceByName :one +-- name: GetKubernetesServiceByName :one SELECT * FROM - services + kubernetes_services WHERE service_name = $1 AND project_id = $2 @@ -193,11 +184,11 @@ LIMIT 1; INSERT INTO user_projects (user_id, project_id) VALUES ($1, $2); --- name: GetProjectBranches :many +-- name: GetKubernetesProjectBranches :many SELECT project_branch FROM - services s + kubernetes_services s WHERE s.project_id = $1 UNION diff --git a/internal/sql/schema.sql b/internal/sql/schema.sql index 7a3dc42..98da106 100644 --- a/internal/sql/schema.sql +++ b/internal/sql/schema.sql @@ -1,3 +1,8 @@ +CREATE TYPE runtime AS ENUM ( + 'docker', + 'kubernetes' +); + CREATE TABLE projects ( id uuid PRIMARY KEY DEFAULT gen_random_uuid (), name text NOT NULL @@ -8,21 +13,83 @@ CREATE TABLE services ( project_id uuid NOT NULL, project_branch text NOT NULL, service_name text NOT NULL, + runtime RUNTIME NOT NULL DEFAULT 'kubernetes', + -- Kubernetes specific node_ports integer[] NULL, ingress text NULL, + -- Docker specific + port_maps text[] NULL, + container_name text NULL, + docker_network text NULL, FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE, UNIQUE (project_id, project_branch, service_name) ); +CREATE OR REPLACE VIEW docker_services AS +SELECT + id, + project_id, + project_branch, + service_name, + runtime, + port_maps, + container_name, + docker_network +FROM + services +WHERE + runtime = 'docker' WITH CHECK OPTION; + +CREATE OR REPLACE VIEW kubernetes_services AS +SELECT + id, + project_id, + project_branch, + service_name, + runtime, + node_ports, + ingress +FROM + services +WHERE + runtime = 'kubernetes' WITH CHECK OPTION; + CREATE TABLE volumes ( identifier uuid PRIMARY KEY, + runtime RUNTIME NOT NULL DEFAULT 'kubernetes', volume_name text NOT NULL, project_id uuid NOT NULL, project_branch text NOT NULL, + -- Kubernetes size integer NOT NULL, FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE ); +CREATE OR REPLACE VIEW docker_volumes AS +SELECT + identifier, + runtime, + volume_name, + project_id, + project_branch +FROM + volumes +WHERE + runtime = 'docker' WITH CHECK OPTION; + +CREATE OR REPLACE VIEW kubernetes_volumes AS +SELECT + identifier, + runtime, + volume_name, + project_id, + project_branch, + size +FROM + volumes +WHERE + runtime = 'kubernetes' WITH CHECK OPTION; + CREATE TABLE users ( id uuid PRIMARY KEY DEFAULT gen_random_uuid (), username text NOT NULL,