From 0ea3863a32fbaede8d5b883ae52296dcfd52a42b Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Wed, 4 Sep 2024 11:18:01 +0530 Subject: [PATCH 01/17] feat: [WIP] environments on kloudlite edge clusters --- .tools/nvim/__http__/console/apps.graphql.yml | 5 +- .../__http__/console/environments.graphql.yml | 9 +- apps/console/Taskfile.yml | 1 + .../internal/app/adapters/account-svc.go | 41 ++ apps/console/internal/app/app.go | 19 +- apps/console/internal/app/grpc-server.go | 4 +- .../internal/app/process-resource-updates.go | 9 + apps/console/internal/domain/api.go | 6 + apps/console/internal/domain/domain.go | 110 +++- .../domain/kloudlite-edge-cluster/domain.go | 9 + .../entities/kloudlite-edge-cluster.go | 14 + .../internal/entities/resource-mapping.go | 2 + apps/console/internal/env/env.go | 14 +- apps/console/internal/framework/framework.go | 9 + .../internal/app/adapter-accounts-svc.go | 3 +- .../internal/domain/global-vpn-devices.go | 32 +- .../field-constants/generated_constants.go | 184 +++--- apps/message-office/Taskfile.yml | 9 + apps/message-office/errors/errors.go | 12 + apps/message-office/internal/app/app.go | 12 +- .../internal/app/internal-grpc-server.go | 80 ++- apps/message-office/internal/domain/api.go | 12 +- apps/message-office/internal/domain/domain.go | 131 ++--- .../internal/domain/entities.go | 24 - .../internal/domain/platform-edge/domain.go | 15 + .../internal/domain/platform-edge/repo.go | 120 ++++ .../domain/platform-edge/repo_test.go | 191 +++++++ .../internal/entities/allocation.go | 80 +++ .../internal/entities/field-constants/gen.go | 3 + .../field-constants/generated_constants.go | 29 + .../entities/platform-edge-cluster.go | 34 ++ .../internal/framework/framework.go | 12 +- .../protobufs/cluster-token.proto | 26 + .../cluster-token/cluster-token.pb.go | 368 ++++++++++++ .../cluster-token/cluster-token_grpc.pb.go | 146 +++++ .../protobufs/platform-edge.proto | 36 ++ .../platform-edge/platform-edge.pb.go | 522 ++++++++++++++++++ .../platform-edge/platform-edge_grpc.pb.go | 183 ++++++ apps/message-office/types/errors.go | 1 + apps/tenant-agent/main.go | 7 - mocks/pkg/k8s/client.go | 4 +- mocks/pkg/repos/dbrepo.go | 15 +- pkg/logging/slog-logger.go | 2 + pkg/repos/db-repo-mongo.go | 40 ++ pkg/repos/db-repo.go | 9 + pkg/repos/mongo.go | 1 + 46 files changed, 2338 insertions(+), 257 deletions(-) create mode 100644 apps/console/internal/app/adapters/account-svc.go create mode 100644 apps/console/internal/domain/kloudlite-edge-cluster/domain.go create mode 100644 apps/console/internal/entities/kloudlite-edge-cluster.go create mode 100644 apps/message-office/errors/errors.go create mode 100644 apps/message-office/internal/domain/platform-edge/domain.go create mode 100644 apps/message-office/internal/domain/platform-edge/repo.go create mode 100644 apps/message-office/internal/domain/platform-edge/repo_test.go create mode 100644 apps/message-office/internal/entities/allocation.go create mode 100644 apps/message-office/internal/entities/field-constants/gen.go create mode 100644 apps/message-office/internal/entities/field-constants/generated_constants.go create mode 100644 apps/message-office/internal/entities/platform-edge-cluster.go create mode 100644 apps/message-office/protobufs/cluster-token.proto create mode 100644 apps/message-office/protobufs/cluster-token/cluster-token.pb.go create mode 100644 apps/message-office/protobufs/cluster-token/cluster-token_grpc.pb.go create mode 100644 apps/message-office/protobufs/platform-edge.proto create mode 100644 apps/message-office/protobufs/platform-edge/platform-edge.pb.go create mode 100644 apps/message-office/protobufs/platform-edge/platform-edge_grpc.pb.go create mode 100644 apps/message-office/types/errors.go diff --git a/.tools/nvim/__http__/console/apps.graphql.yml b/.tools/nvim/__http__/console/apps.graphql.yml index c94e2da84..79296ef1e 100644 --- a/.tools/nvim/__http__/console/apps.graphql.yml +++ b/.tools/nvim/__http__/console/apps.graphql.yml @@ -1,6 +1,7 @@ --- global: name: sample-app + envName: "test-env" --- label: List Apps @@ -117,9 +118,7 @@ variables: name: '{{.name}}' spec: services: - - type: tcp - port: 80 - targetPort: 80 + - port: 80 containers: - name: main image: kong/httpbin diff --git a/.tools/nvim/__http__/console/environments.graphql.yml b/.tools/nvim/__http__/console/environments.graphql.yml index f59b734f7..de567dc8f 100644 --- a/.tools/nvim/__http__/console/environments.graphql.yml +++ b/.tools/nvim/__http__/console/environments.graphql.yml @@ -76,7 +76,7 @@ query: |+ #graphql variables: env: displayName: Display Name of a sample environment - clusterName: "{{.gcpClusterName}}" + clusterName: "__kloudlite_enabled_cluster" metadata: name: "{{.envName}}" # spec: @@ -121,12 +121,11 @@ variables: label: "delete environment" query: |+ - mutation Core_deleteEnvironment($projectName: String!, $envName: String!) { - core_deleteEnvironment(projectName: $projectName, envName: $envName) + mutation Core_deleteEnvironment($envName: String!) { + core_deleteEnvironment(envName: $envName) } variables: - projectName: "{{.projectName}}" - envName: "{{.clonedEnvName}}" + envName: "{{.envName}}" --- --- diff --git a/apps/console/Taskfile.yml b/apps/console/Taskfile.yml index 322f64544..c02a4b2e6 100644 --- a/apps/console/Taskfile.yml +++ b/apps/console/Taskfile.yml @@ -55,6 +55,7 @@ tasks: cmds: - go build -o bin/console ./main.go - ./bin/console --dev + # - go run . --dev gen:constants: cmds: diff --git a/apps/console/internal/app/adapters/account-svc.go b/apps/console/internal/app/adapters/account-svc.go new file mode 100644 index 000000000..d3d257738 --- /dev/null +++ b/apps/console/internal/app/adapters/account-svc.go @@ -0,0 +1,41 @@ +package adapters + +import ( + "context" + "time" + + "github.com/kloudlite/operator/pkg/errors" + + "github.com/kloudlite/api/apps/console/internal/domain" + "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/accounts" +) + +type accountsSvc struct { + accountsRPC accounts.AccountsClient +} + +// GetAccount implements domain.AccountsSvc. +func (as *accountsSvc) GetAccountRegion(ctx context.Context, userId string, accountName string) (string, error) { + nctx, cf := context.WithTimeout(ctx, 2*time.Second) + defer cf() + out, err := as.accountsRPC.GetAccount(nctx, &accounts.GetAccountIn{ + UserId: userId, + AccountName: accountName, + }) + if err != nil { + // if errors.Is(err, context.DeadlineExceeded) { + // return nil, domain.ErrGRPCCall{Err: err} + // } + return "", errors.NewE(err) + } + + return out.GetKloudliteGatewayRegion(), nil +} + +func NewAccountsSvc(accountsClient accounts.AccountsClient) domain.AccountsSvc { + return &accountsSvc{ + accountsRPC: accountsClient, + } +} + +var _ domain.AccountsSvc = (*accountsSvc)(nil) diff --git a/apps/console/internal/app/app.go b/apps/console/internal/app/app.go index bea14a365..ebe01870d 100644 --- a/apps/console/internal/app/app.go +++ b/apps/console/internal/app/app.go @@ -4,6 +4,7 @@ import ( "context" "log/slog" + "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/accounts" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/console" "github.com/kloudlite/api/pkg/k8s" @@ -13,11 +14,13 @@ import ( "github.com/gofiber/fiber/v2" "go.uber.org/fx" + "github.com/kloudlite/api/apps/console/internal/app/adapters" "github.com/kloudlite/api/apps/console/internal/app/graph" "github.com/kloudlite/api/apps/console/internal/app/graph/generated" "github.com/kloudlite/api/apps/console/internal/domain" "github.com/kloudlite/api/apps/console/internal/entities" "github.com/kloudlite/api/apps/console/internal/env" + platform_edge "github.com/kloudlite/api/apps/message-office/protobufs/platform-edge" "github.com/kloudlite/api/common" "github.com/kloudlite/api/constants" "github.com/kloudlite/api/grpc-interfaces/infra" @@ -34,8 +37,10 @@ import ( ) type ( - IAMGrpcClient grpc.Client - InfraClient grpc.Client + IAMGrpcClient grpc.Client + InfraClient grpc.Client + MessageOfficeInternalClient grpc.Client + AccountsClient grpc.Client ) type ( @@ -81,6 +86,16 @@ var Module = fx.Module("app", }, ), + fx.Provide(func(conn MessageOfficeInternalClient) platform_edge.PlatformEdgeClient { + return platform_edge.NewPlatformEdgeClient(conn) + }), + + fx.Provide(func(conn AccountsClient) accounts.AccountsClient { + return accounts.NewAccountsClient(conn) + }), + + fx.Provide(adapters.NewAccountsSvc), + fx.Invoke( func(server httpServer.Server, d domain.Domain, sessionRepo kv.Repo[*common.AuthSession], ev *env.Env) { gqlConfig := generated.Config{Resolvers: &graph.Resolver{Domain: d, EnvVars: ev}} diff --git a/apps/console/internal/app/grpc-server.go b/apps/console/internal/app/grpc-server.go index 4e956cd76..13e5d16fb 100644 --- a/apps/console/internal/app/grpc-server.go +++ b/apps/console/internal/app/grpc-server.go @@ -24,12 +24,12 @@ func (g *grpcServer) ArchiveResourcesForCluster(ctx context.Context, in *console AccountName: in.AccountName, } - archiveStatus, err := g.d.ArchiveEnvironmentsForCluster(consoleCtx, in.ClusterName) + _, err := g.d.ArchiveEnvironmentsForCluster(consoleCtx, in.ClusterName) if err != nil { return &console.ArchiveResourcesForClusterOut{Archived: false}, err } - archiveStatus, err = g.d.ArchiveClusterManagedServicesForCluster(consoleCtx, in.ClusterName) + archiveStatus, err := g.d.ArchiveClusterManagedServicesForCluster(consoleCtx, in.ClusterName) if err != nil { return &console.ArchiveResourcesForClusterOut{Archived: false}, err } diff --git a/apps/console/internal/app/process-resource-updates.go b/apps/console/internal/app/process-resource-updates.go index 73469bebf..340636a97 100644 --- a/apps/console/internal/app/process-resource-updates.go +++ b/apps/console/internal/app/process-resource-updates.go @@ -12,6 +12,7 @@ import ( "github.com/kloudlite/api/apps/console/internal/domain" "github.com/kloudlite/api/apps/console/internal/entities" msgOfficeT "github.com/kloudlite/api/apps/message-office/types" + "github.com/kloudlite/api/constants" "github.com/kloudlite/api/pkg/errors" fn "github.com/kloudlite/api/pkg/functions" "github.com/kloudlite/api/pkg/messaging" @@ -141,6 +142,7 @@ func ProcessResourceUpdates(consumer ResourceUpdateConsumer, d domain.Domain, lo switch gvkStr { case environmentGVK.String(): { + dctx.AccountName = rwu.Object.GetLabels()[constants.AccountNameKey] var ws entities.Environment if err := fn.JsonConversion(rwu.Object, &ws); err != nil { return errors.NewE(err) @@ -153,11 +155,18 @@ func ProcessResourceUpdates(consumer ResourceUpdateConsumer, d domain.Domain, lo } case appsGVK.String(): { + if ru.AccountName == "nxt-multi-tenancy" { + } + + dctx.AccountName = rwu.Object.GetLabels()[constants.AccountNameKey] + var app entities.App if err := fn.JsonConversion(rwu.Object, &app); err != nil { return errors.NewE(err) } + // rctx := domain.ResourceContext{ConsoleContext: dctx, EnvironmentName: rwu.Object.GetLabels()[constants.EnvNameKey]} + rctx, err := getResourceContext(dctx, entities.ResourceTypeApp, ru.ClusterName, obj) if err != nil { return errors.NewE(err) diff --git a/apps/console/internal/domain/api.go b/apps/console/internal/domain/api.go index 52b574555..fea90a50c 100644 --- a/apps/console/internal/domain/api.go +++ b/apps/console/internal/domain/api.go @@ -136,7 +136,13 @@ type UpdateAndDeleteOpts struct { ClusterName string } +type AccountsSvc interface { + GetAccountRegion(ctx context.Context, userId string, accountName string) (string, error) +} + type Domain interface { + AccountsSvc + CheckNameAvailability(ctx context.Context, accountName string, environmentName *string, msvcName *string, resType entities.ResourceType, name string) (*CheckNameAvailabilityOutput, error) // INFO: project have been disabled diff --git a/apps/console/internal/domain/domain.go b/apps/console/internal/domain/domain.go index ddf0fc44c..42a139535 100644 --- a/apps/console/internal/domain/domain.go +++ b/apps/console/internal/domain/domain.go @@ -10,6 +10,7 @@ import ( "github.com/kloudlite/api/pkg/logging" + mo_errors "github.com/kloudlite/api/apps/message-office/errors" "github.com/kloudlite/api/pkg/errors" "github.com/kloudlite/api/common" @@ -20,6 +21,7 @@ import ( "github.com/kloudlite/api/constants" + platform_edge "github.com/kloudlite/api/apps/message-office/protobufs/platform-edge" t "github.com/kloudlite/api/apps/tenant-agent/types" "go.uber.org/fx" "sigs.k8s.io/controller-runtime/pkg/client" @@ -43,8 +45,10 @@ type domain struct { producer MessageDispatcher - iamClient iam.IAMClient - infraClient infra.InfraClient + iamClient iam.IAMClient + infraClient infra.InfraClient + platformEdgeClient platform_edge.PlatformEdgeClient + AccountsSvc environmentRepo repos.DbRepo[*entities.Environment] @@ -99,6 +103,7 @@ func addTrackingId(obj client.Object, id repos.ID) { type K8sContext interface { context.Context + GetUserId() repos.ID GetAccountName() string } @@ -142,9 +147,12 @@ func (d *domain) applyK8sResourceOnCluster(ctx K8sContext, clusterName string, o return errors.NewE(err) } -// func (d *domain) applyK8sResource(ctx K8sContext, clusterName string, obj client.Object, recordVersion int) error {|} - func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Object, recordVersion int) error { + var dispatchAddr struct { + AccountName string + ClusterName string + } + clusterName, err := d.getClusterAttachedToEnvironment(ctx, envName) if err != nil { return errors.NewE(err) @@ -155,10 +163,55 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj return nil } + switch *clusterName { + case "__kloudlite_enabled_cluster": + { + // dispatchAddr.AccountName = "kloudlite-edge-platform" + // dispatchAddr.ClusterName = "kl-edge-1" + + allocatedEdge, err := d.platformEdgeClient.GetAllocatedPlatformEdgeCluster(ctx, &platform_edge.GetAllocatedPlatformEdgeClusterIn{AccountName: ctx.GetAccountName()}) + if err != nil { + if !errors.Is(err, mo_errors.ErrEdgeClusterNotAllocated) { + return errors.NewEf(err, "failed to get allocated edge cluster") + } + + // INFO: not allocated, allocating a new one + accountRegion, err := d.GetAccountRegion(ctx, string(ctx.GetUserId()), ctx.GetAccountName()) + if err != nil { + return errors.NewEf(err, "failed to get account region") + } + + allocatedEdge, err = d.platformEdgeClient.AllocatePlatformEdgeCluster(ctx, &platform_edge.AllocatePlatformEdgeClusterIn{ + Region: accountRegion, + AccountName: ctx.GetAccountName(), + }) + if err != nil { + return errors.NewEf(err, "failed to allocate platform edge cluster") + } + } + + dispatchAddr.AccountName = allocatedEdge.OwnedByAccount + dispatchAddr.ClusterName = allocatedEdge.ClusterName + } + default: + { + dispatchAddr.AccountName = ctx.GetAccountName() + dispatchAddr.ClusterName = *clusterName + } + } + if obj.GetObjectKind().GroupVersionKind().Empty() { return errors.Newf("object GVK is not set, can not apply") } + labels := obj.GetLabels() + if labels == nil { + labels = make(map[string]string, 2) + } + labels[constants.AccountNameKey] = ctx.GetAccountName() + labels[constants.EnvNameKey] = envName + obj.SetLabels(labels) + ann := obj.GetAnnotations() if ann == nil { ann = make(map[string]string, 1) @@ -170,9 +223,10 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj if err != nil { return errors.NewE(err) } + b, err := json.Marshal(t.AgentMessage{ - AccountName: ctx.GetAccountName(), - ClusterName: *clusterName, + AccountName: dispatchAddr.AccountName, + ClusterName: dispatchAddr.ClusterName, Action: t.ActionApply, Object: m, }) @@ -180,7 +234,7 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj return errors.NewE(err) } - subject := common.SendToAgentSubjectName(ctx.GetAccountName(), *clusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) + subject := common.SendToAgentSubjectName(dispatchAddr.AccountName, dispatchAddr.ClusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) err = d.producer.Produce(ctx, msgTypes.ProduceMsg{ Subject: subject, @@ -311,6 +365,28 @@ func (d *domain) deleteK8sResource(ctx K8sContext, environmentName string, obj c return ErrNoClusterAttached } + var dispatchAddr struct { + AccountName string + ClusterName string + } + + switch *clusterName { + case "__kloudlite_enabled_cluster": + { + // dispatchAddr.AccountName = "kloudlite-edge-platform" + // dispatchAddr.ClusterName = "kl-edge-1" + + dispatchAddr.AccountName = "nxt-multi-tenancy" + dispatchAddr.ClusterName = "sample" + } + default: + { + + dispatchAddr.AccountName = ctx.GetAccountName() + dispatchAddr.ClusterName = *clusterName + } + } + if obj.GetObjectKind().GroupVersionKind().Empty() { return errors.Newf("object GVK is not set, can not apply") } @@ -320,8 +396,8 @@ func (d *domain) deleteK8sResource(ctx K8sContext, environmentName string, obj c return errors.NewE(err) } b, err := json.Marshal(t.AgentMessage{ - AccountName: ctx.GetAccountName(), - ClusterName: *clusterName, + AccountName: dispatchAddr.AccountName, + ClusterName: dispatchAddr.ClusterName, Action: t.ActionDelete, Object: m, }) @@ -329,7 +405,7 @@ func (d *domain) deleteK8sResource(ctx K8sContext, environmentName string, obj c return errors.NewE(err) } - subject := common.SendToAgentSubjectName(ctx.GetAccountName(), *clusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) + subject := common.SendToAgentSubjectName(dispatchAddr.AccountName, dispatchAddr.ClusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) err = d.producer.Produce(ctx, msgTypes.ProduceMsg{ Subject: subject, @@ -555,6 +631,8 @@ var Module = fx.Module("domain", iamClient iam.IAMClient, infraClient infra.InfraClient, + platformEdgeClient platform_edge.PlatformEdgeClient, + accountsSvc AccountsSvc, environmentRepo repos.DbRepo[*entities.Environment], registryImageRepo repos.DbRepo[*entities.RegistryImage], @@ -583,9 +661,12 @@ var Module = fx.Module("domain", producer: producer, - iamClient: iamClient, - infraClient: infraClient, - logger: logger, + iamClient: iamClient, + infraClient: infraClient, + platformEdgeClient: platformEdgeClient, + AccountsSvc: accountsSvc, + + logger: logger, environmentRepo: environmentRepo, appRepo: appRepo, @@ -606,5 +687,4 @@ var Module = fx.Module("domain", resourceEventPublisher: resourceEventPublisher, consoleCacheStore: consoleCacheStore, } - }), -) + })) diff --git a/apps/console/internal/domain/kloudlite-edge-cluster/domain.go b/apps/console/internal/domain/kloudlite-edge-cluster/domain.go new file mode 100644 index 000000000..86791723e --- /dev/null +++ b/apps/console/internal/domain/kloudlite-edge-cluster/domain.go @@ -0,0 +1,9 @@ +package kloudlite_edge_cluster + +import "context" + +type PickEdgeClusterArgs struct{} + +func PickEdgeCluster(ctx context.Context, args *PickEdgeClusterArgs) (any, error) { + return nil, nil +} diff --git a/apps/console/internal/entities/kloudlite-edge-cluster.go b/apps/console/internal/entities/kloudlite-edge-cluster.go new file mode 100644 index 000000000..83b0e21d2 --- /dev/null +++ b/apps/console/internal/entities/kloudlite-edge-cluster.go @@ -0,0 +1,14 @@ +package entities + +import "github.com/kloudlite/api/pkg/repos" + +type KLoudliteEdgeCluster struct { + repos.BaseEntity `json:",inline"` + Region string `json:"region"` + Name string `json:"name"` + + NumAccounts int `json:"num_accounts"` + MaxNumAccounts int `json:"max_num_accounts"` + + Comments string `json:"comments"` +} diff --git a/apps/console/internal/entities/resource-mapping.go b/apps/console/internal/entities/resource-mapping.go index 987ef6eca..855cdab36 100644 --- a/apps/console/internal/entities/resource-mapping.go +++ b/apps/console/internal/entities/resource-mapping.go @@ -28,6 +28,8 @@ const ( ResourceHeirarchyEnvironment ResourceHeirarchy = "environment" ) +// ResourceMapping represents a relationship +// between a resource (i.e. Environment, App, Router etc.) with it's {account, cluster and environment} type ResourceMapping struct { repos.BaseEntity `bson:",inline"` diff --git a/apps/console/internal/env/env.go b/apps/console/internal/env/env.go index 4d7b08fa1..7e6582252 100644 --- a/apps/console/internal/env/env.go +++ b/apps/console/internal/env/env.go @@ -11,9 +11,8 @@ type Env struct { DNSAddr string `env:"DNS_ADDR" required:"true"` KloudliteDNSSuffix string `env:"KLOUDLITE_DNS_SUFFIX" required:"true"` - - ConsoleDBUri string `env:"MONGO_URI" required:"true"` - ConsoleDBName string `env:"MONGO_DB_NAME" required:"true"` + ConsoleDBUri string `env:"MONGO_URI" required:"true"` + ConsoleDBName string `env:"MONGO_DB_NAME" required:"true"` AccountCookieName string `env:"ACCOUNT_COOKIE_NAME" required:"true"` ClusterCookieName string `env:"CLUSTER_COOKIE_NAME" required:"true"` @@ -24,14 +23,17 @@ type Env struct { WebhookTokenHashingSecret string `env:"WEBHOOK_TOKEN_HASHING_SECRET" required:"true"` WebhookURL string `env:"WEBHOOK_URL" required:"true"` - IAMGrpcAddr string `env:"IAM_GRPC_ADDR" required:"true"` - InfraGrpcAddr string `env:"INFRA_GRPC_ADDR" required:"true"` + IAMGrpcAddr string `env:"IAM_GRPC_ADDR" required:"true"` + InfraGrpcAddr string `env:"INFRA_GRPC_ADDR" required:"true"` + MessageOfficeInternalGRPCAddr string `env:"MESSAGE_OFFICE_INTERNAL_GRPC_ADDR" required:"true"` + AccountGRPCAddr string `env:"ACCOUNT_GRPC_ADDR" required:"true"` PromHttpAddr string `env:"PROM_HTTP_ADDR" required:"true"` SessionKVBucket string `env:"SESSION_KV_BUCKET" required:"true"` ConsoleCacheKVBucket string `env:"CONSOLE_CACHE_KV_BUCKET" required:"true"` IsDev bool - KubernetesApiProxy string `env:"KUBERNETES_API_PROXY"` + + KubernetesApiProxy string `env:"KUBERNETES_API_PROXY" default:"localhost:8080"` DeviceNamespace string `env:"DEVICE_NAMESPACE" required:"true"` } diff --git a/apps/console/internal/framework/framework.go b/apps/console/internal/framework/framework.go index 29c707a23..03cda93a8 100644 --- a/apps/console/internal/framework/framework.go +++ b/apps/console/internal/framework/framework.go @@ -68,6 +68,7 @@ var Module = fx.Module("framework", return k8s.NewClient(restCfg, nil) }), + // grpc clients fx.Provide(func(ev *env.Env) (app.IAMGrpcClient, error) { return grpc.NewGrpcClient(ev.IAMGrpcAddr) }), @@ -76,6 +77,14 @@ var Module = fx.Module("framework", return grpc.NewGrpcClient(ev.InfraGrpcAddr) }), + fx.Provide(func(ev *env.Env) (app.AccountsClient, error) { + return grpc.NewGrpcClient(ev.AccountGRPCAddr) + }), + + fx.Provide(func(ev *env.Env) (app.MessageOfficeInternalClient, error) { + return grpc.NewGrpcClient(ev.MessageOfficeInternalGRPCAddr) + }), + fx.Invoke(func(lf fx.Lifecycle, c1 app.IAMGrpcClient, c2 app.InfraClient) { lf.Append(fx.Hook{ OnStop: func(context.Context) error { diff --git a/apps/infra/internal/app/adapter-accounts-svc.go b/apps/infra/internal/app/adapter-accounts-svc.go index 3f6d4e66b..d171c1172 100644 --- a/apps/infra/internal/app/adapter-accounts-svc.go +++ b/apps/infra/internal/app/adapter-accounts-svc.go @@ -3,9 +3,10 @@ package app import ( "context" "errors" - errors2 "github.com/kloudlite/operator/pkg/errors" "time" + errors2 "github.com/kloudlite/operator/pkg/errors" + "github.com/kloudlite/api/apps/infra/internal/domain" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/accounts" ) diff --git a/apps/infra/internal/domain/global-vpn-devices.go b/apps/infra/internal/domain/global-vpn-devices.go index 1cf65e0f4..a9e34a8a1 100644 --- a/apps/infra/internal/domain/global-vpn-devices.go +++ b/apps/infra/internal/domain/global-vpn-devices.go @@ -331,9 +331,26 @@ func (d *domain) buildGlobalVPNDeviceWgBaseParams(ctx InfraContext, gvpnConns [] return nil, deviceHosts, err } - pubPeers = append(gvpnConnPeers, pubPeers...) + publicPeers := make([]wgutils.PublicPeer, 0, len(pubPeers)+len(gvpnConnPeers)) + + for _, peer := range gvpnConnPeers { + deviceHosts[peer.DNSHostname] = peer.IP + if peer.DNSHostname == fmt.Sprintf("%s.device.local", gvpnDevice.Name) { + continue + } + if peer.PublicEndpoint == nil { + privPeers = append(privPeers, peer) + continue + } + + publicPeers = append(publicPeers, wgutils.PublicPeer{ + DisplayName: fmt.Sprintf("Global VPN Gateway (%s)", peer.Comments), + PublicKey: peer.PublicKey, + AllowedIPs: peer.AllowedIPs, + Endpoint: *peer.PublicEndpoint, + }) + } - publicPeers := make([]wgutils.PublicPeer, 0, len(pubPeers)) for _, peer := range pubPeers { deviceHosts[peer.DNSHostname] = peer.IP if peer.DNSHostname == fmt.Sprintf("%s.device.local", gvpnDevice.Name) { @@ -343,8 +360,10 @@ func (d *domain) buildGlobalVPNDeviceWgBaseParams(ctx InfraContext, gvpnConns [] privPeers = append(privPeers, peer) continue } + publicPeers = append(publicPeers, wgutils.PublicPeer{ - DisplayName: peer.DNSHostname, + // DisplayName: peer.DNSHostname, + DisplayName: fmt.Sprintf("Global VPN Device [%s] (%s)", peer.Comments, peer.DNSHostname), PublicKey: peer.PublicKey, AllowedIPs: peer.AllowedIPs, Endpoint: *peer.PublicEndpoint, @@ -358,9 +377,10 @@ func (d *domain) buildGlobalVPNDeviceWgBaseParams(ctx InfraContext, gvpnConns [] continue } privatePeers = append(privatePeers, wgutils.PrivatePeer{ - DisplayName: peer.DNSHostname, - PublicKey: peer.PublicKey, - AllowedIPs: peer.AllowedIPs, + DisplayName: fmt.Sprintf("Global VPN Device [%s] (%s)", peer.Comments, peer.DNSHostname), + // DisplayName: peer.DNSHostname, + PublicKey: peer.PublicKey, + AllowedIPs: peer.AllowedIPs, }) } diff --git a/apps/infra/internal/entities/field-constants/generated_constants.go b/apps/infra/internal/entities/field-constants/generated_constants.go index ef1ba1463..a4986510c 100644 --- a/apps/infra/internal/entities/field-constants/generated_constants.go +++ b/apps/infra/internal/entities/field-constants/generated_constants.go @@ -564,6 +564,7 @@ const ( PersistentVolumeSpecStorageosSecretRefUid = "spec.storageos.secretRef.uid" PersistentVolumeSpecStorageosVolumeName = "spec.storageos.volumeName" PersistentVolumeSpecStorageosVolumeNamespace = "spec.storageos.volumeNamespace" + PersistentVolumeSpecVolumeAttributesClassName = "spec.volumeAttributesClassName" PersistentVolumeSpecVolumeMode = "spec.volumeMode" PersistentVolumeSpecVsphereVolume = "spec.vsphereVolume" PersistentVolumeSpecVsphereVolumeFsType = "spec.vsphereVolume.fsType" @@ -574,27 +575,27 @@ const ( // constant vars generated for struct PersistentVolumeClaim const ( - PersistentVolumeClaimSpec = "spec" - PersistentVolumeClaimSpecAccessModes = "spec.accessModes" - PersistentVolumeClaimSpecDataSource = "spec.dataSource" - PersistentVolumeClaimSpecDataSourceApiGroup = "spec.dataSource.apiGroup" - PersistentVolumeClaimSpecDataSourceKind = "spec.dataSource.kind" - PersistentVolumeClaimSpecDataSourceName = "spec.dataSource.name" - PersistentVolumeClaimSpecDataSourceRef = "spec.dataSourceRef" - PersistentVolumeClaimSpecDataSourceRefApiGroup = "spec.dataSourceRef.apiGroup" - PersistentVolumeClaimSpecDataSourceRefKind = "spec.dataSourceRef.kind" - PersistentVolumeClaimSpecDataSourceRefName = "spec.dataSourceRef.name" - PersistentVolumeClaimSpecDataSourceRefNamespace = "spec.dataSourceRef.namespace" - PersistentVolumeClaimSpecResources = "spec.resources" - PersistentVolumeClaimSpecResourcesClaims = "spec.resources.claims" - PersistentVolumeClaimSpecResourcesLimits = "spec.resources.limits" - PersistentVolumeClaimSpecResourcesRequests = "spec.resources.requests" - PersistentVolumeClaimSpecSelector = "spec.selector" - PersistentVolumeClaimSpecSelectorMatchExpressions = "spec.selector.matchExpressions" - PersistentVolumeClaimSpecSelectorMatchLabels = "spec.selector.matchLabels" - PersistentVolumeClaimSpecStorageClassName = "spec.storageClassName" - PersistentVolumeClaimSpecVolumeMode = "spec.volumeMode" - PersistentVolumeClaimSpecVolumeName = "spec.volumeName" + PersistentVolumeClaimSpec = "spec" + PersistentVolumeClaimSpecAccessModes = "spec.accessModes" + PersistentVolumeClaimSpecDataSource = "spec.dataSource" + PersistentVolumeClaimSpecDataSourceApiGroup = "spec.dataSource.apiGroup" + PersistentVolumeClaimSpecDataSourceKind = "spec.dataSource.kind" + PersistentVolumeClaimSpecDataSourceName = "spec.dataSource.name" + PersistentVolumeClaimSpecDataSourceRef = "spec.dataSourceRef" + PersistentVolumeClaimSpecDataSourceRefApiGroup = "spec.dataSourceRef.apiGroup" + PersistentVolumeClaimSpecDataSourceRefKind = "spec.dataSourceRef.kind" + PersistentVolumeClaimSpecDataSourceRefName = "spec.dataSourceRef.name" + PersistentVolumeClaimSpecDataSourceRefNamespace = "spec.dataSourceRef.namespace" + PersistentVolumeClaimSpecResources = "spec.resources" + PersistentVolumeClaimSpecResourcesLimits = "spec.resources.limits" + PersistentVolumeClaimSpecResourcesRequests = "spec.resources.requests" + PersistentVolumeClaimSpecSelector = "spec.selector" + PersistentVolumeClaimSpecSelectorMatchExpressions = "spec.selector.matchExpressions" + PersistentVolumeClaimSpecSelectorMatchLabels = "spec.selector.matchLabels" + PersistentVolumeClaimSpecStorageClassName = "spec.storageClassName" + PersistentVolumeClaimSpecVolumeAttributesClassName = "spec.volumeAttributesClassName" + PersistentVolumeClaimSpecVolumeMode = "spec.volumeMode" + PersistentVolumeClaimSpecVolumeName = "spec.volumeName" ) // constant vars generated for struct VolumeAttachment @@ -776,6 +777,7 @@ const ( VolumeAttachmentSpecSourceInlineVolumeSpecStorageosSecretRefUid = "spec.source.inlineVolumeSpec.storageos.secretRef.uid" VolumeAttachmentSpecSourceInlineVolumeSpecStorageosVolumeName = "spec.source.inlineVolumeSpec.storageos.volumeName" VolumeAttachmentSpecSourceInlineVolumeSpecStorageosVolumeNamespace = "spec.source.inlineVolumeSpec.storageos.volumeNamespace" + VolumeAttachmentSpecSourceInlineVolumeSpecVolumeAttributesClassName = "spec.source.inlineVolumeSpec.volumeAttributesClassName" VolumeAttachmentSpecSourceInlineVolumeSpecVolumeMode = "spec.source.inlineVolumeSpec.volumeMode" VolumeAttachmentSpecSourceInlineVolumeSpecVsphereVolume = "spec.source.inlineVolumeSpec.vsphereVolume" VolumeAttachmentSpecSourceInlineVolumeSpecVsphereVolumeFsType = "spec.source.inlineVolumeSpec.vsphereVolume.fsType" @@ -798,72 +800,76 @@ const ( // constant vars generated for struct const ( - AccountName = "accountName" - ApiVersion = "apiVersion" - ClusterName = "clusterName" - CreatedBy = "createdBy" - CreatedByUserEmail = "createdBy.userEmail" - CreatedByUserId = "createdBy.userId" - CreatedByUserName = "createdBy.userName" - CreationTime = "creationTime" - DisplayName = "displayName" - Id = "id" - Kind = "kind" - LastUpdatedBy = "lastUpdatedBy" - LastUpdatedByUserEmail = "lastUpdatedBy.userEmail" - LastUpdatedByUserId = "lastUpdatedBy.userId" - LastUpdatedByUserName = "lastUpdatedBy.userName" - MarkedForDeletion = "markedForDeletion" - Metadata = "metadata" - MetadataAnnotations = "metadata.annotations" - MetadataCreationTimestamp = "metadata.creationTimestamp" - MetadataDeletionGracePeriodSeconds = "metadata.deletionGracePeriodSeconds" - MetadataDeletionTimestamp = "metadata.deletionTimestamp" - MetadataFinalizers = "metadata.finalizers" - MetadataGenerateName = "metadata.generateName" - MetadataGeneration = "metadata.generation" - MetadataLabels = "metadata.labels" - MetadataManagedFields = "metadata.managedFields" - MetadataName = "metadata.name" - MetadataNamespace = "metadata.namespace" - MetadataOwnerReferences = "metadata.ownerReferences" - MetadataResourceVersion = "metadata.resourceVersion" - MetadataSelfLink = "metadata.selfLink" - MetadataUid = "metadata.uid" - RecordVersion = "recordVersion" - Status = "status" - StatusAccessModes = "status.accessModes" - StatusAllocatedResourceStatuses = "status.allocatedResourceStatuses" - StatusAllocatedResources = "status.allocatedResources" - StatusAttachError = "status.attachError" - StatusAttachErrorMessage = "status.attachError.message" - StatusAttachErrorTime = "status.attachError.time" - StatusAttached = "status.attached" - StatusAttachmentMetadata = "status.attachmentMetadata" - StatusCapacity = "status.capacity" - StatusCheckList = "status.checkList" - StatusChecks = "status.checks" - StatusConditions = "status.conditions" - StatusDetachError = "status.detachError" - StatusDetachErrorMessage = "status.detachError.message" - StatusDetachErrorTime = "status.detachError.time" - StatusIsReady = "status.isReady" - StatusLastPhaseTransitionTime = "status.lastPhaseTransitionTime" - StatusLastReadyGeneration = "status.lastReadyGeneration" - StatusLastReconcileTime = "status.lastReconcileTime" - StatusMessage = "status.message" - StatusMessageItems = "status.message.items" - StatusPhase = "status.phase" - StatusReason = "status.reason" - StatusReleaseNotes = "status.releaseNotes" - StatusReleaseStatus = "status.releaseStatus" - StatusResources = "status.resources" - SyncStatus = "syncStatus" - SyncStatusAction = "syncStatus.action" - SyncStatusError = "syncStatus.error" - SyncStatusLastSyncedAt = "syncStatus.lastSyncedAt" - SyncStatusRecordVersion = "syncStatus.recordVersion" - SyncStatusState = "syncStatus.state" - SyncStatusSyncScheduledAt = "syncStatus.syncScheduledAt" - UpdateTime = "updateTime" + AccountName = "accountName" + ApiVersion = "apiVersion" + ClusterName = "clusterName" + CreatedBy = "createdBy" + CreatedByUserEmail = "createdBy.userEmail" + CreatedByUserId = "createdBy.userId" + CreatedByUserName = "createdBy.userName" + CreationTime = "creationTime" + DisplayName = "displayName" + Id = "id" + Kind = "kind" + LastUpdatedBy = "lastUpdatedBy" + LastUpdatedByUserEmail = "lastUpdatedBy.userEmail" + LastUpdatedByUserId = "lastUpdatedBy.userId" + LastUpdatedByUserName = "lastUpdatedBy.userName" + MarkedForDeletion = "markedForDeletion" + Metadata = "metadata" + MetadataAnnotations = "metadata.annotations" + MetadataCreationTimestamp = "metadata.creationTimestamp" + MetadataDeletionGracePeriodSeconds = "metadata.deletionGracePeriodSeconds" + MetadataDeletionTimestamp = "metadata.deletionTimestamp" + MetadataFinalizers = "metadata.finalizers" + MetadataGenerateName = "metadata.generateName" + MetadataGeneration = "metadata.generation" + MetadataLabels = "metadata.labels" + MetadataManagedFields = "metadata.managedFields" + MetadataName = "metadata.name" + MetadataNamespace = "metadata.namespace" + MetadataOwnerReferences = "metadata.ownerReferences" + MetadataResourceVersion = "metadata.resourceVersion" + MetadataSelfLink = "metadata.selfLink" + MetadataUid = "metadata.uid" + RecordVersion = "recordVersion" + Status = "status" + StatusAccessModes = "status.accessModes" + StatusAllocatedResourceStatuses = "status.allocatedResourceStatuses" + StatusAllocatedResources = "status.allocatedResources" + StatusAttachError = "status.attachError" + StatusAttachErrorMessage = "status.attachError.message" + StatusAttachErrorTime = "status.attachError.time" + StatusAttached = "status.attached" + StatusAttachmentMetadata = "status.attachmentMetadata" + StatusCapacity = "status.capacity" + StatusCheckList = "status.checkList" + StatusChecks = "status.checks" + StatusConditions = "status.conditions" + StatusCurrentVolumeAttributesClassName = "status.currentVolumeAttributesClassName" + StatusDetachError = "status.detachError" + StatusDetachErrorMessage = "status.detachError.message" + StatusDetachErrorTime = "status.detachError.time" + StatusIsReady = "status.isReady" + StatusLastPhaseTransitionTime = "status.lastPhaseTransitionTime" + StatusLastReadyGeneration = "status.lastReadyGeneration" + StatusLastReconcileTime = "status.lastReconcileTime" + StatusMessage = "status.message" + StatusMessageItems = "status.message.items" + StatusModifyVolumeStatus = "status.modifyVolumeStatus" + StatusModifyVolumeStatusStatus = "status.modifyVolumeStatus.status" + StatusModifyVolumeStatusTargetVolumeAttributesClassName = "status.modifyVolumeStatus.targetVolumeAttributesClassName" + StatusPhase = "status.phase" + StatusReason = "status.reason" + StatusReleaseNotes = "status.releaseNotes" + StatusReleaseStatus = "status.releaseStatus" + StatusResources = "status.resources" + SyncStatus = "syncStatus" + SyncStatusAction = "syncStatus.action" + SyncStatusError = "syncStatus.error" + SyncStatusLastSyncedAt = "syncStatus.lastSyncedAt" + SyncStatusRecordVersion = "syncStatus.recordVersion" + SyncStatusState = "syncStatus.state" + SyncStatusSyncScheduledAt = "syncStatus.syncScheduledAt" + UpdateTime = "updateTime" ) diff --git a/apps/message-office/Taskfile.yml b/apps/message-office/Taskfile.yml index 1ec38087d..79b4419f1 100644 --- a/apps/message-office/Taskfile.yml +++ b/apps/message-office/Taskfile.yml @@ -33,6 +33,15 @@ tasks: out: "{{.binary}}-{{.GOARCH}}" GOARCH: "{{.GOARCH}}" + gen:constants: + cmds: + - go generate ./internal/entities/field-constants/gen.go + + grpc:build: + dir: ./protobufs/ + cmds: + - protoc --go_out=. --go-grpc_out=. --go_opt=paths=import --go-grpc_opt=paths=import ./*.proto + container:build-and-push: requires: vars: diff --git a/apps/message-office/errors/errors.go b/apps/message-office/errors/errors.go new file mode 100644 index 000000000..8130f3cbd --- /dev/null +++ b/apps/message-office/errors/errors.go @@ -0,0 +1,12 @@ +package errors + +import "errors" + +// github.com/kloudlite/api/apps/message-office/internal/domain/platform-edge/repo.go +var ErrEdgeClusterNotAllocated = errors.New("edge cluster not allocated") + +// github.com/kloudlite/api/apps/message-office/internal/domain/platform-edge/repo.go +var ( + ErrNoClusterAvailable = errors.New("no cluster available") + ErrNoClustersInRegion = errors.New("no clusters found in region") +) diff --git a/apps/message-office/internal/app/app.go b/apps/message-office/internal/app/app.go index e81c88f18..553e910a5 100644 --- a/apps/message-office/internal/app/app.go +++ b/apps/message-office/internal/app/app.go @@ -8,9 +8,9 @@ import ( "github.com/kloudlite/api/apps/message-office/internal/app/graph/generated" proto_rpc "github.com/kloudlite/api/apps/message-office/internal/app/proto-rpc" "github.com/kloudlite/api/apps/message-office/internal/domain" + "github.com/kloudlite/api/apps/message-office/internal/entities" "github.com/kloudlite/api/apps/message-office/internal/env" "github.com/kloudlite/api/grpc-interfaces/infra" - message_office_internal "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/message-office-internal" "github.com/kloudlite/api/pkg/grpc" httpServer "github.com/kloudlite/api/pkg/http-server" "github.com/kloudlite/api/pkg/logging" @@ -27,12 +27,12 @@ type ( type ( ExternalGrpcServer grpc.Server - InternalGrpcServer grpc.Server ) var Module = fx.Module("app", repos.NewFxMongoRepo[*domain.MessageOfficeToken]("mo_tokens", "mot", domain.MOTokenIndexes), - repos.NewFxMongoRepo[*domain.AccessToken]("acc_tokens", "acct", domain.AccessTokenIndexes), + repos.NewFxMongoRepo[*entities.PlatformEdgeCluster]("platform_edge_clusters", "pec", entities.PlatformEdgeClusterIndexes), + repos.NewFxMongoRepo[*entities.ClusterAllocation]("cluster_allocations", "ca", entities.ClusterAllocationIndexes), fx.Provide(func(jsc *nats.JetstreamClient, logger logging.Logger) UpdatesProducer { return msg_nats.NewJetstreamProducer(jsc) @@ -72,11 +72,9 @@ var Module = fx.Module("app", } }), + // internal grpc server fx.Provide(newInternalMsgServer), - - fx.Invoke(func(server InternalGrpcServer, internalMsgServer message_office_internal.MessageOfficeInternalServer) { - message_office_internal.RegisterMessageOfficeInternalServer(server, internalMsgServer) - }), + fx.Invoke(RegisterInternalMsgServer), fx.Invoke( func(server ExternalGrpcServer, messageServer messages.MessageDispatchServiceServer) { diff --git a/apps/message-office/internal/app/internal-grpc-server.go b/apps/message-office/internal/app/internal-grpc-server.go index 66b9d7d5c..42c5da560 100644 --- a/apps/message-office/internal/app/internal-grpc-server.go +++ b/apps/message-office/internal/app/internal-grpc-server.go @@ -4,35 +4,91 @@ import ( "context" "github.com/kloudlite/api/apps/message-office/internal/domain" - "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/message-office-internal" + cluster_token "github.com/kloudlite/api/apps/message-office/protobufs/cluster-token" + platform_edge "github.com/kloudlite/api/apps/message-office/protobufs/platform-edge" "github.com/kloudlite/api/pkg/errors" + "github.com/kloudlite/api/pkg/grpc" ) -type internalMsgServer struct { +type ( + InternalGrpcServer grpc.Server +) + +type internalServer struct { d domain.Domain - message_office_internal.UnimplementedMessageOfficeInternalServer + // message_office_internal.UnimplementedMessageOfficeInternalServer + cluster_token.UnimplementedClusterTokenServer + platform_edge.UnimplementedPlatformEdgeServer } -func (s *internalMsgServer) GenerateClusterToken(ctx context.Context, in *message_office_internal.GenerateClusterTokenIn) (*message_office_internal.GenerateClusterTokenOut, error) { +// GenerateClusterToken implements cluster_token.ClusterTokenServer. +func (s *internalServer) GenerateClusterToken(ctx context.Context, in *cluster_token.GenerateClusterTokenIn) (*cluster_token.GenerateClusterTokenOut, error) { token, err := s.d.GenClusterToken(ctx, in.AccountName, in.ClusterName) if err != nil { return nil, errors.NewE(err) } - return &message_office_internal.GenerateClusterTokenOut{ - ClusterToken: token, - }, nil + + return &cluster_token.GenerateClusterTokenOut{ClusterToken: token}, nil } -func (s *internalMsgServer) GetClusterToken(ctx context.Context, in *message_office_internal.GetClusterTokenIn) (*message_office_internal.GetClusterTokenOut, error) { +// GetClusterToken implements cluster_token.ClusterTokenServer. +func (s *internalServer) GetClusterToken(ctx context.Context, in *cluster_token.GetClusterTokenIn) (*cluster_token.GetClusterTokenOut, error) { token, err := s.d.GetClusterToken(ctx, in.AccountName, in.ClusterName) if err != nil { return nil, errors.NewE(err) } - return &message_office_internal.GetClusterTokenOut{ - ClusterToken: token, + return &cluster_token.GetClusterTokenOut{ClusterToken: token}, nil +} + +// AllocatePlatformEdgeCluster implements platform_edge.PlatformEdgeServer. +func (s *internalServer) AllocatePlatformEdgeCluster(ctx context.Context, in *platform_edge.AllocatePlatformEdgeClusterIn) (*platform_edge.AllocatePlatformEdgeClusterOut, error) { + pec, err := s.d.AllocatePlatformEdgeCluster(ctx, in.Region, in.AccountName) + if err != nil { + return nil, errors.NewE(err) + } + + return &platform_edge.AllocatePlatformEdgeClusterOut{ClusterName: pec.Name}, nil +} + +// GetAllocatedPlatformEdgeCluster implements platform_edge.PlatformEdgeServer. +func (s *internalServer) GetAllocatedPlatformEdgeCluster(ctx context.Context, in *platform_edge.GetAllocatedPlatformEdgeClusterIn) (*platform_edge.AllocatePlatformEdgeClusterOut, error) { + allocated, err := s.d.GetAllocatedPlatformEdgeCluster(ctx, in.AccountName) + if err != nil { + return nil, errors.NewE(err) + } + + return &platform_edge.AllocatePlatformEdgeClusterOut{ + ClusterName: allocated.Cluster.Name, + OwnedByAccount: allocated.Cluster.OwnedByAccount, }, nil } -func newInternalMsgServer(d domain.Domain) message_office_internal.MessageOfficeInternalServer { - return &internalMsgServer{d: d} +// ListPlatformEdgeClusters implements platform_edge.PlatformEdgeServer. +func (s *internalServer) ListPlatformEdgeClusters(ctx context.Context, in *platform_edge.ListPlatformEdgeClustersIn) (*platform_edge.ListPlatformEdgeClustersOut, error) { + pec, err := s.d.ListPlatformEdgeClusters(ctx, &in.Region) + if err != nil { + return nil, errors.NewE(err) + } + + out := &platform_edge.ListPlatformEdgeClustersOut{ + PlatformEdgeClusters: make([]*platform_edge.PlatformEdgeCluster, 0, len(pec)), + } + + for _, pec := range pec { + out.PlatformEdgeClusters = append(out.PlatformEdgeClusters, &platform_edge.PlatformEdgeCluster{ + Region: pec.Region, + ClusterName: pec.Name, + }) + } + return out, nil +} + +func newInternalMsgServer(d domain.Domain) (cluster_token.ClusterTokenServer, platform_edge.PlatformEdgeServer) { + server := &internalServer{d: d} + return server, server +} + +func RegisterInternalMsgServer(server InternalGrpcServer, cts cluster_token.ClusterTokenServer, pes platform_edge.PlatformEdgeServer) { + cluster_token.RegisterClusterTokenServer(server, cts) + platform_edge.RegisterPlatformEdgeServer(server, pes) } diff --git a/apps/message-office/internal/domain/api.go b/apps/message-office/internal/domain/api.go index 493f90cb5..82cbedabe 100644 --- a/apps/message-office/internal/domain/api.go +++ b/apps/message-office/internal/domain/api.go @@ -1,11 +1,17 @@ package domain -import "context" +import ( + "context" + + platform_edge "github.com/kloudlite/api/apps/message-office/internal/domain/platform-edge" +) type Domain interface { GenClusterToken(ctx context.Context, accountName string, clusterName string) (string, error) FindClusterToken(ctx context.Context, clusterToken string) (*MessageOfficeToken, error) GetClusterToken(ctx context.Context, accountName string, clusterName string) (string, error) - GenAccessToken(ctx context.Context, clusterToken string) (*AccessToken, error) - ValidateAccessToken(ctx context.Context, accessToken, accountName, clusterName string) error + // GenAccessToken(ctx context.Context, clusterToken string) (*AccessToken, error) + // ValidateAccessToken(ctx context.Context, accessToken, accountName, clusterName string) error + + platform_edge.Domain } diff --git a/apps/message-office/internal/domain/domain.go b/apps/message-office/internal/domain/domain.go index 83a4e0421..abc9544f4 100644 --- a/apps/message-office/internal/domain/domain.go +++ b/apps/message-office/internal/domain/domain.go @@ -2,40 +2,46 @@ package domain import ( "context" + "log/slog" "github.com/kloudlite/api/pkg/errors" "go.uber.org/fx" + platform_edge "github.com/kloudlite/api/apps/message-office/internal/domain/platform-edge" "github.com/kloudlite/api/apps/message-office/internal/env" fn "github.com/kloudlite/api/pkg/functions" - "github.com/kloudlite/api/pkg/logging" "github.com/kloudlite/api/pkg/repos" ) -type domain struct { - moRepo repos.DbRepo[*MessageOfficeToken] - env *env.Env - accessTokenRepo repos.DbRepo[*AccessToken] - logger logging.Logger +type PlatformEdgeDomain struct { + *platform_edge.Repo } -func (d *domain) ValidateAccessToken(ctx context.Context, accessToken string, accountName string, clusterName string) error { - r, err := d.accessTokenRepo.FindOne(ctx, repos.Filter{ - "accessToken": accessToken, - "accountName": accountName, - "clusterName": clusterName, - }) - if err != nil { - return errors.NewE(err) - } - - if r == nil { - return errors.Newf("invalid access token") - } +type domain struct { + moRepo repos.DbRepo[*MessageOfficeToken] + env *env.Env + logger *slog.Logger - return nil + PlatformEdgeDomain } +// func (d *domain) ValidateAccessToken(ctx context.Context, accessToken string, accountName string, clusterName string) error { +// r, err := d.accessTokenRepo.FindOne(ctx, repos.Filter{ +// "accessToken": accessToken, +// "accountName": accountName, +// "clusterName": clusterName, +// }) +// if err != nil { +// return errors.NewE(err) +// } +// +// if r == nil { +// return errors.Newf("invalid access token") +// } +// +// return nil +// } + func (d *domain) getClusterToken(ctx context.Context, accountName string, clusterName string) (string, error) { if accountName == "" || clusterName == "" { return "", errors.Newf("accountName and/or clusterName cannot be empty") @@ -84,55 +90,56 @@ func (d *domain) GenClusterToken(ctx context.Context, accountName, clusterName s return record.Token, nil } -func (d *domain) GenAccessToken(ctx context.Context, clusterToken string) (*AccessToken, error) { - mot, err := d.moRepo.FindOne(ctx, repos.Filter{"token": clusterToken}) - if err != nil { - return nil, errors.NewE(err) - } - - if mot == nil { - return nil, errors.Newf("no such cluster token found") - } - - if mot.Granted != nil && *mot.Granted { - d.logger.Infof("a valid access-token has already been issued for this cluster token, granting a new one, and removing the old one") - } - - record, err := d.accessTokenRepo.Upsert(ctx, repos.Filter{ - "accountName": mot.AccountName, - "clusterName": mot.ClusterName, - }, &AccessToken{ - AccountName: mot.AccountName, - ClusterName: mot.ClusterName, - AccessToken: fn.CleanerNanoidOrDie(40), - }) - if err != nil { - return nil, errors.NewE(err) - } - - if record == nil { - return nil, errors.Newf("failed to upsert into accessToken collection") - } - - mot.Granted = fn.New(true) - if _, err := d.moRepo.UpdateById(ctx, mot.Id, mot); err != nil { - return nil, errors.NewE(err) - } - - return record, nil -} +// func (d *domain) GenAccessToken(ctx context.Context, clusterToken string) (*AccessToken, error) { +// mot, err := d.moRepo.FindOne(ctx, repos.Filter{"token": clusterToken}) +// if err != nil { +// return nil, errors.NewE(err) +// } +// +// if mot == nil { +// return nil, errors.Newf("no such cluster token found") +// } +// +// if mot.Granted != nil && *mot.Granted { +// d.logger.Infof("a valid access-token has already been issued for this cluster token, granting a new one, and removing the old one") +// } +// +// record, err := d.accessTokenRepo.Upsert(ctx, repos.Filter{ +// "accountName": mot.AccountName, +// "clusterName": mot.ClusterName, +// }, &AccessToken{ +// AccountName: mot.AccountName, +// ClusterName: mot.ClusterName, +// AccessToken: fn.CleanerNanoidOrDie(40), +// }) +// if err != nil { +// return nil, errors.NewE(err) +// } +// +// if record == nil { +// return nil, errors.Newf("failed to upsert into accessToken collection") +// } +// +// mot.Granted = fn.New(true) +// if _, err := d.moRepo.UpdateById(ctx, mot.Id, mot); err != nil { +// return nil, errors.NewE(err) +// } +// +// return record, nil +// } var Module = fx.Module( "domain", fx.Provide(func( moRepo repos.DbRepo[*MessageOfficeToken], - accessTokenRepo repos.DbRepo[*AccessToken], - logger logging.Logger, + // accessTokenRepo repos.DbRepo[*AccessToken], + logger *slog.Logger, ) Domain { return &domain{ - moRepo: moRepo, - accessTokenRepo: accessTokenRepo, - logger: logger, + moRepo: moRepo, + // accessTokenRepo: accessTokenRepo, + logger: logger, + PlatformEdgeDomain: PlatformEdgeDomain{Repo: &platform_edge.Repo{}}, } }), ) diff --git a/apps/message-office/internal/domain/entities.go b/apps/message-office/internal/domain/entities.go index 8215ebb79..d233544d9 100644 --- a/apps/message-office/internal/domain/entities.go +++ b/apps/message-office/internal/domain/entities.go @@ -26,27 +26,3 @@ var MOTokenIndexes = []repos.IndexField{ Unique: true, }, } - -type AccessToken struct { - repos.BaseEntity `json:",inline"` - AccountName string `json:"accountName"` - ClusterName string `json:"clusterName"` - AccessToken string `json:"accessToken"` -} - -var AccessTokenIndexes = []repos.IndexField{ - { - Field: []repos.IndexKey{ - {Key: "id", Value: repos.IndexAsc}, - }, - Unique: true, - }, - { - Field: []repos.IndexKey{ - {Key: "accountName", Value: repos.IndexAsc}, - {Key: "clusterName", Value: repos.IndexAsc}, - {Key: "accessToken", Value: repos.IndexAsc}, - }, - Unique: true, - }, -} diff --git a/apps/message-office/internal/domain/platform-edge/domain.go b/apps/message-office/internal/domain/platform-edge/domain.go new file mode 100644 index 000000000..64d39d975 --- /dev/null +++ b/apps/message-office/internal/domain/platform-edge/domain.go @@ -0,0 +1,15 @@ +package platform_edge + +import ( + "context" + + "github.com/kloudlite/api/apps/message-office/internal/entities" +) + +type Domain interface { + AllocatePlatformEdgeCluster(ctx context.Context, region string, account string) (*entities.PlatformEdgeCluster, error) + GetAllocatedPlatformEdgeCluster(ctx context.Context, account string) (*entities.ClusterAllocation, error) + ListPlatformEdgeClusters(ctx context.Context, region *string) ([]*entities.PlatformEdgeCluster, error) +} + +var _ Domain = (*Repo)(nil) diff --git a/apps/message-office/internal/domain/platform-edge/repo.go b/apps/message-office/internal/domain/platform-edge/repo.go new file mode 100644 index 000000000..8321c754f --- /dev/null +++ b/apps/message-office/internal/domain/platform-edge/repo.go @@ -0,0 +1,120 @@ +package platform_edge + +import ( + "context" + + mo_errors "github.com/kloudlite/api/apps/message-office/errors" + "github.com/kloudlite/api/pkg/errors" + + "github.com/kloudlite/api/apps/message-office/internal/entities" + fc "github.com/kloudlite/api/apps/message-office/internal/entities/field-constants" + "github.com/kloudlite/api/pkg/repos" +) + +type Repo struct { + edge_clusters repos.DbRepo[*entities.PlatformEdgeCluster] + allocated_clusters repos.DbRepo[*entities.ClusterAllocation] +} + +func (r *Repo) ListPlatformEdgeClusters(ctx context.Context, region *string) ([]*entities.PlatformEdgeCluster, error) { + q := repos.Query{} + if region != nil { + q.Filter = repos.Filter{ + fc.PlatformEdgeClusterRegion: region, + } + } + return r.edge_clusters.Find(ctx, q) +} + +func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, account string) (*entities.PlatformEdgeCluster, error) { + m, err := r.allocated_clusters.GroupByAndCount(ctx, repos.Filter{fc.ClusterAllocationClusterRegion: region}, fc.ClusterAllocationClusterName, repos.GroupByAndCountOptions{ + Limit: 1, + Sort: repos.SortDirectionAsc, + }) + if err != nil { + return nil, err + } + + if len(m) > 1 { + return nil, errors.New("more than one cluster available") + } + + var clusterName string + + switch len(m) { + case 0: + { + x, err := r.edge_clusters.FindOne(ctx, repos.Filter{fc.PlatformEdgeClusterRegion: region}) + if err != nil { + return nil, err + } + if x == nil { + return nil, mo_errors.ErrNoClustersInRegion + } + + clusterName = x.Name + + if _, err := r.allocated_clusters.Create(ctx, &entities.ClusterAllocation{ + To: account, + Cluster: entities.ClusterAllocationCluster{ + Name: clusterName, + Region: region, + OwnedByAccount: x.OwnedByAccount, + }, + }); err != nil { + return nil, err + } + } + case 1: + { + for k := range m { + clusterName = k + break + } + } + } + + pec, err := r.edge_clusters.FindOne(ctx, repos.Filter{ + fc.PlatformEdgeClusterName: clusterName, + fc.PlatformEdgeClusterRegion: region, + }) + if err != nil { + return nil, err + } + + if pec == nil { + return nil, mo_errors.ErrNoClustersInRegion + } + + return pec, nil +} + +func (r *Repo) GetPlatformEdgeCluster(ctx context.Context, clusterName string) (*entities.PlatformEdgeCluster, error) { + pec, err := r.edge_clusters.FindOne(ctx, repos.Filter{ + fc.PlatformEdgeClusterName: clusterName, + }) + if err != nil { + return nil, err + } + + if pec == nil { + return nil, errors.New("cluster not found") + } + + return pec, nil +} + +func (r *Repo) GetAllocatedPlatformEdgeCluster(ctx context.Context, account string) (*entities.ClusterAllocation, error) { + rec, err := r.allocated_clusters.FindOne(ctx, repos.Filter{ + fc.ClusterAllocationTo: account, + }) + if err != nil { + return nil, err + } + + if rec == nil { + return nil, mo_errors.ErrEdgeClusterNotAllocated + } + + return rec, nil +} diff --git a/apps/message-office/internal/domain/platform-edge/repo_test.go b/apps/message-office/internal/domain/platform-edge/repo_test.go new file mode 100644 index 000000000..d9820f493 --- /dev/null +++ b/apps/message-office/internal/domain/platform-edge/repo_test.go @@ -0,0 +1,191 @@ +package platform_edge + +import ( + "context" + "reflect" + "testing" + + "github.com/kloudlite/api/apps/message-office/internal/entities" + fc "github.com/kloudlite/api/apps/message-office/internal/entities/field-constants" + mock_repos "github.com/kloudlite/api/mocks/pkg/repos" + + // fn "github.com/kloudlite/api/pkg/functions" + mo_errors "github.com/kloudlite/api/apps/message-office/errors" + "github.com/kloudlite/api/pkg/errors" + "github.com/kloudlite/api/pkg/repos" +) + +func TestRepo_AllocatePlatformEdgeCluster(t *testing.T) { + type fields struct { + edge_clusters func(t *testing.T) repos.DbRepo[*entities.PlatformEdgeCluster] + allocated_clusters func(t *testing.T) repos.DbRepo[*entities.ClusterAllocation] + } + type args struct { + ctx context.Context + region string + account string + } + tests := []struct { + name string + fields fields + args args + want *entities.PlatformEdgeCluster + wantErr error + }{ + { + name: "[region] not found", + fields: fields{ + edge_clusters: func(t *testing.T) repos.DbRepo[*entities.PlatformEdgeCluster] { + repo := mock_repos.NewDbRepo[*entities.PlatformEdgeCluster]() + + repo.MockFindOne = func(ctx context.Context, filter repos.Filter) (*entities.PlatformEdgeCluster, error) { + return nil, nil + } + + return repo + }, + allocated_clusters: func(t *testing.T) repos.DbRepo[*entities.ClusterAllocation] { + repo := mock_repos.NewDbRepo[*entities.ClusterAllocation]() + repo.MockGroupByAndCount = func(ctx context.Context, filter repos.Filter, groupBy string, opts repos.GroupByAndCountOptions) (map[string]int64, error) { + return nil, nil + } + return repo + }, + }, + args: args{ + ctx: context.Background(), + region: "REGION", + account: "sample-account", + }, + want: nil, + wantErr: mo_errors.ErrNoClustersInRegion, + }, + + { + name: "[region] found, but no allocation till now", + fields: fields{ + edge_clusters: func(t *testing.T) repos.DbRepo[*entities.PlatformEdgeCluster] { + repo := mock_repos.NewDbRepo[*entities.PlatformEdgeCluster]() + + repo.MockFindOne = func(ctx context.Context, filter repos.Filter) (*entities.PlatformEdgeCluster, error) { + return &entities.PlatformEdgeCluster{ + BaseEntity: repos.BaseEntity{Id: "1"}, + Name: "sample-cluster", + Region: "REGION", + CloudProvider: "sample-cloud-provider", + }, nil + } + + return repo + }, + allocated_clusters: func(t *testing.T) repos.DbRepo[*entities.ClusterAllocation] { + repo := mock_repos.NewDbRepo[*entities.ClusterAllocation]() + + repo.MockGroupByAndCount = func(ctx context.Context, filter repos.Filter, groupBy string, opts repos.GroupByAndCountOptions) (map[string]int64, error) { + return nil, nil + } + + repo.MockCreate = func(ctx context.Context, data *entities.ClusterAllocation) (*entities.ClusterAllocation, error) { + if data.Cluster.Name != "sample-cluster" { + t.Errorf("Repo.AllocatePlatformEdgeCluster() called with wrong cluster name") + } + return data, nil + } + + return repo + }, + }, + args: args{ + ctx: context.Background(), + region: "REGION", + account: "sample-account", + }, + want: &entities.PlatformEdgeCluster{ + BaseEntity: repos.BaseEntity{Id: "1"}, + Name: "sample-cluster", + Region: "REGION", + CloudProvider: "sample-cloud-provider", + }, + wantErr: mo_errors.ErrNoClustersInRegion, + }, + + { + name: "[allocations] found", + fields: fields{ + edge_clusters: func(t *testing.T) repos.DbRepo[*entities.PlatformEdgeCluster] { + repo := mock_repos.NewDbRepo[*entities.PlatformEdgeCluster]() + + repo.MockFindOne = func(ctx context.Context, filter repos.Filter) (*entities.PlatformEdgeCluster, error) { + if filter[fc.PlatformEdgeClusterName] != "sample-cluster" { + t.Errorf("edge_clusters.FindOne() called with wrong cluster name") + t.FailNow() + } + + if filter[fc.PlatformEdgeClusterRegion] != "REGION" { + t.Errorf("edge_clusters.FindOne() called with wrong region") + t.FailNow() + } + + return &entities.PlatformEdgeCluster{ + BaseEntity: repos.BaseEntity{Id: "1"}, + Name: "sample-cluster", + Region: "REGION", + CloudProvider: "sample-cloud-provider", + }, nil + } + + return repo + }, + allocated_clusters: func(t *testing.T) repos.DbRepo[*entities.ClusterAllocation] { + repo := mock_repos.NewDbRepo[*entities.ClusterAllocation]() + + repo.MockGroupByAndCount = func(ctx context.Context, filter repos.Filter, groupBy string, opts repos.GroupByAndCountOptions) (map[string]int64, error) { + return map[string]int64{"sample-cluster": 1}, nil + } + + repo.MockCreate = func(ctx context.Context, data *entities.ClusterAllocation) (*entities.ClusterAllocation, error) { + if data.Cluster.Name != "sample-cluster" { + t.Errorf("allocated_clusters.AllocatePlatformEdgeCluster() called with wrong cluster name") + } + + if data.Cluster.Region != "REGION" { + t.Errorf("allocated_clusters.AllocatePlatformEdgeCluster() called with wrong region") + } + + return data, nil + } + + return repo + }, + }, + args: args{ + ctx: context.Background(), + region: "REGION", + account: "sample-account", + }, + want: &entities.PlatformEdgeCluster{ + BaseEntity: repos.BaseEntity{Id: "1"}, + Name: "sample-cluster", + Region: "REGION", + CloudProvider: "sample-cloud-provider", + }, + wantErr: mo_errors.ErrNoClustersInRegion, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := &Repo{ + edge_clusters: tt.fields.edge_clusters(t), + allocated_clusters: tt.fields.allocated_clusters(t), + } + got, err := r.AllocatePlatformEdgeCluster(tt.args.ctx, tt.args.region, tt.args.account) + if (err != nil) && !errors.Is(err, tt.wantErr) { + t.Errorf("Repo.AllocatePlatformEdgeCluster()\n\terror = %v,\n\twantErr = %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Repo.AllocatePlatformEdgeCluster()\n\tgot = %#v,\n\twant %#v", got, tt.want) + } + }) + } +} diff --git a/apps/message-office/internal/entities/allocation.go b/apps/message-office/internal/entities/allocation.go new file mode 100644 index 000000000..64c2e9a49 --- /dev/null +++ b/apps/message-office/internal/entities/allocation.go @@ -0,0 +1,80 @@ +package entities + +import ( + fc "github.com/kloudlite/api/apps/message-office/internal/entities/field-constants" + "github.com/kloudlite/api/pkg/repos" +) + +type ClusterAllocationCluster struct { + Name string `json:"name"` + Region string `json:"region"` + OwnedByAccount string `json:"owned_by_account"` +} + +type ClusterAllocation struct { + repos.BaseEntity `json:",inline"` + To string `json:"to"` + Cluster ClusterAllocationCluster `json:"cluster"` +} + +var ClusterAllocationIndexes = []repos.IndexField{ + { + Field: []repos.IndexKey{ + {Key: fc.Id, Value: repos.IndexAsc}, + }, + Unique: true, + }, + { + Field: []repos.IndexKey{ + {Key: fc.ClusterAllocationTo, Value: repos.IndexAsc}, + {Key: fc.ClusterAllocationClusterName, Value: repos.IndexAsc}, + }, + Unique: true, + }, + { + Field: []repos.IndexKey{ + {Key: fc.ClusterAllocationClusterRegion, Value: repos.IndexAsc}, + }, + }, +} + +/* +```javascript +records = [] +for (let i = 1000; i < 10000; i++) { + records.push({ + id: i, + to: `A-${i}`, + cluster_name: `cluster-${Math.ceil(Math.random() * 10)}` + }); +} +db.cluster_allocations.insertMany(records); + +// [ +// { id: "1", to: "A", cluster_name: "cluster-1" }, +// { id: "2", to: "B", cluster_name: "cluster-1" }, +// { id: "3", to: "C", cluster_name: "cluster-2" }, +// { id: "4", to: "D", cluster_name: "cluster-2" }, +// { id: "5", to: "E", cluster_name: "cluster-3" }, +// { id: "6", to: "F", cluster_name: "cluster-3" }, +// { id: "7", to: "G", cluster_name: "cluster-4" }, +// ] +// ); + +db.cluster_allocations.aggregate([ + { + $group: { + _id: "$cluster_name", // Replace with the field you want to group by + count: { $sum: 1 } // Count the number of occurrences + } + }, + { + $sort: { count: 1 } // Sort by count in descending order + }, + { + $limit: 1 // Limit the results to the top 10 + } +]) + +``` +*/ diff --git a/apps/message-office/internal/entities/field-constants/gen.go b/apps/message-office/internal/entities/field-constants/gen.go new file mode 100644 index 000000000..acf290950 --- /dev/null +++ b/apps/message-office/internal/entities/field-constants/gen.go @@ -0,0 +1,3 @@ +package field_constants + +//go:generate go run github.com/kloudlite/api/cmd/struct-json-path --pkg github.com/kloudlite/api/apps/message-office/internal/entities --common-path "metadata" --common-path "apiVersion" --common-path "kind" --common-path "status" --common-path "syncStatus" --common-path "lastUpdatedBy" --common-path "createdBy" --common-path "displayName" --common-path "creationTime" --common-path "updateTime" --common-path "id" --common-path "recordVersion" --common-path "accountName" --common-path "projectName" --common-path "environmentName" --common-path "clusterName" --common-path "markedForDeletion" --out-file ./generated_constants.go --banner "package field_constants" --ignore-nesting "time.Time" --ignore-nesting "k8s.io/apimachinery/pkg/apis/meta/v1.Time" diff --git a/apps/message-office/internal/entities/field-constants/generated_constants.go b/apps/message-office/internal/entities/field-constants/generated_constants.go new file mode 100644 index 000000000..8749ba63c --- /dev/null +++ b/apps/message-office/internal/entities/field-constants/generated_constants.go @@ -0,0 +1,29 @@ +// DO NOT EDIT. generated by "github.com/kloudlite/api/cmd/struct-json-path" + +package field_constants + +// constant vars generated for struct ClusterAllocation +const ( + ClusterAllocationCluster = "cluster" + ClusterAllocationClusterName = "cluster.name" + ClusterAllocationClusterOwnedByAccount = "cluster.owned_by_account" + ClusterAllocationClusterRegion = "cluster.region" + ClusterAllocationTo = "to" +) + +// constant vars generated for struct PlatformEdgeCluster +const ( + PlatformEdgeClusterCloudProvider = "cloud_provider" + PlatformEdgeClusterName = "name" + PlatformEdgeClusterOwnedByAccount = "owned_by_account" + PlatformEdgeClusterRegion = "region" +) + +// constant vars generated for struct +const ( + CreationTime = "creationTime" + Id = "id" + MarkedForDeletion = "markedForDeletion" + RecordVersion = "recordVersion" + UpdateTime = "updateTime" +) diff --git a/apps/message-office/internal/entities/platform-edge-cluster.go b/apps/message-office/internal/entities/platform-edge-cluster.go new file mode 100644 index 000000000..b1f77408a --- /dev/null +++ b/apps/message-office/internal/entities/platform-edge-cluster.go @@ -0,0 +1,34 @@ +package entities + +import ( + fc "github.com/kloudlite/api/apps/message-office/internal/entities/field-constants" + "github.com/kloudlite/api/pkg/repos" +) + +type PlatformEdgeCluster struct { + repos.BaseEntity `json:",inline"` + OwnedByAccount string `json:"owned_by_account"` + Name string `json:"name"` + Region string `json:"region"` + CloudProvider string `json:"cloud_provider"` +} + +var PlatformEdgeClusterIndexes = []repos.IndexField{ + { + Field: []repos.IndexKey{ + {Key: fc.Id, Value: repos.IndexAsc}, + }, + Unique: true, + }, + { + Field: []repos.IndexKey{ + {Key: fc.PlatformEdgeClusterName, Value: repos.IndexAsc}, + }, + Unique: true, + }, + { + Field: []repos.IndexKey{ + {Key: fc.PlatformEdgeClusterOwnedByAccount, Value: repos.IndexAsc}, + }, + }, +} diff --git a/apps/message-office/internal/framework/framework.go b/apps/message-office/internal/framework/framework.go index 74faecb5d..9806e6d6a 100644 --- a/apps/message-office/internal/framework/framework.go +++ b/apps/message-office/internal/framework/framework.go @@ -54,10 +54,8 @@ var Module = fx.Module("framework", app.Module, - fx.Provide(func(logr logging.Logger) (app.InternalGrpcServer, error) { - return grpc.NewGrpcServer(grpc.ServerOpts{ - Logger: logr.WithName("internal-grpc-server"), - }) + fx.Provide(func(logger *slog.Logger) (app.InternalGrpcServer, error) { + return grpc.NewGrpcServer(grpc.ServerOpts{Slogger: logger.With(slog.String("component", "internal-grpc"))}) }), fx.Invoke(func(lf fx.Lifecycle, logr logging.Logger, server app.InternalGrpcServer, ev *env.Env) { @@ -81,10 +79,8 @@ var Module = fx.Module("framework", return grpc.NewGrpcClient(ev.InfraGRPCAddr) }), - fx.Provide(func(logr logging.Logger) (app.ExternalGrpcServer, error) { - return grpc.NewGrpcServer(grpc.ServerOpts{ - Logger: logr.WithName("external-grpc-server"), - }) + fx.Provide(func(logger *slog.Logger) (app.ExternalGrpcServer, error) { + return grpc.NewGrpcServer(grpc.ServerOpts{Slogger: logger.With(slog.String("component", "external-grpc"))}) }), fx.Invoke(func(lf fx.Lifecycle, logr logging.Logger, server app.ExternalGrpcServer, ev *env.Env) { diff --git a/apps/message-office/protobufs/cluster-token.proto b/apps/message-office/protobufs/cluster-token.proto new file mode 100644 index 000000000..eb984ca69 --- /dev/null +++ b/apps/message-office/protobufs/cluster-token.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +option go_package = "./cluster-token"; + +service ClusterToken { + rpc GenerateClusterToken(GenerateClusterTokenIn) returns (GenerateClusterTokenOut); + rpc GetClusterToken(GetClusterTokenIn) returns (GetClusterTokenOut); +} + +message GenerateClusterTokenIn { + string accountName = 1; + string clusterName = 2; +} + +message GenerateClusterTokenOut { + string clusterToken = 1; +} + +message GetClusterTokenIn { + string accountName = 1; + string clusterName = 2; +} + +message GetClusterTokenOut { + string clusterToken = 1; +} diff --git a/apps/message-office/protobufs/cluster-token/cluster-token.pb.go b/apps/message-office/protobufs/cluster-token/cluster-token.pb.go new file mode 100644 index 000000000..953a5daad --- /dev/null +++ b/apps/message-office/protobufs/cluster-token/cluster-token.pb.go @@ -0,0 +1,368 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.24.4 +// source: cluster-token.proto + +package cluster_token + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GenerateClusterTokenIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccountName string `protobuf:"bytes,1,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,2,opt,name=clusterName,proto3" json:"clusterName,omitempty"` +} + +func (x *GenerateClusterTokenIn) Reset() { + *x = GenerateClusterTokenIn{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_token_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenerateClusterTokenIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateClusterTokenIn) ProtoMessage() {} + +func (x *GenerateClusterTokenIn) ProtoReflect() protoreflect.Message { + mi := &file_cluster_token_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenerateClusterTokenIn.ProtoReflect.Descriptor instead. +func (*GenerateClusterTokenIn) Descriptor() ([]byte, []int) { + return file_cluster_token_proto_rawDescGZIP(), []int{0} +} + +func (x *GenerateClusterTokenIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *GenerateClusterTokenIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +type GenerateClusterTokenOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterToken string `protobuf:"bytes,1,opt,name=clusterToken,proto3" json:"clusterToken,omitempty"` +} + +func (x *GenerateClusterTokenOut) Reset() { + *x = GenerateClusterTokenOut{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_token_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenerateClusterTokenOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenerateClusterTokenOut) ProtoMessage() {} + +func (x *GenerateClusterTokenOut) ProtoReflect() protoreflect.Message { + mi := &file_cluster_token_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenerateClusterTokenOut.ProtoReflect.Descriptor instead. +func (*GenerateClusterTokenOut) Descriptor() ([]byte, []int) { + return file_cluster_token_proto_rawDescGZIP(), []int{1} +} + +func (x *GenerateClusterTokenOut) GetClusterToken() string { + if x != nil { + return x.ClusterToken + } + return "" +} + +type GetClusterTokenIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccountName string `protobuf:"bytes,1,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,2,opt,name=clusterName,proto3" json:"clusterName,omitempty"` +} + +func (x *GetClusterTokenIn) Reset() { + *x = GetClusterTokenIn{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_token_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClusterTokenIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClusterTokenIn) ProtoMessage() {} + +func (x *GetClusterTokenIn) ProtoReflect() protoreflect.Message { + mi := &file_cluster_token_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClusterTokenIn.ProtoReflect.Descriptor instead. +func (*GetClusterTokenIn) Descriptor() ([]byte, []int) { + return file_cluster_token_proto_rawDescGZIP(), []int{2} +} + +func (x *GetClusterTokenIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *GetClusterTokenIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +type GetClusterTokenOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterToken string `protobuf:"bytes,1,opt,name=clusterToken,proto3" json:"clusterToken,omitempty"` +} + +func (x *GetClusterTokenOut) Reset() { + *x = GetClusterTokenOut{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_token_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClusterTokenOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClusterTokenOut) ProtoMessage() {} + +func (x *GetClusterTokenOut) ProtoReflect() protoreflect.Message { + mi := &file_cluster_token_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClusterTokenOut.ProtoReflect.Descriptor instead. +func (*GetClusterTokenOut) Descriptor() ([]byte, []int) { + return file_cluster_token_proto_rawDescGZIP(), []int{3} +} + +func (x *GetClusterTokenOut) GetClusterToken() string { + if x != nil { + return x.ClusterToken + } + return "" +} + +var File_cluster_token_proto protoreflect.FileDescriptor + +var file_cluster_token_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5c, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x12, + 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x17, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4f, 0x75, 0x74, 0x12, 0x22, + 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x22, 0x57, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x38, 0x0a, 0x12, 0x47, + 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4f, 0x75, + 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0x95, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x49, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x17, + 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x1a, 0x18, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4f, 0x75, + 0x74, 0x12, 0x3a, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x12, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x1a, 0x13, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4f, 0x75, 0x74, 0x42, 0x11, 0x5a, + 0x0f, 0x2e, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_cluster_token_proto_rawDescOnce sync.Once + file_cluster_token_proto_rawDescData = file_cluster_token_proto_rawDesc +) + +func file_cluster_token_proto_rawDescGZIP() []byte { + file_cluster_token_proto_rawDescOnce.Do(func() { + file_cluster_token_proto_rawDescData = protoimpl.X.CompressGZIP(file_cluster_token_proto_rawDescData) + }) + return file_cluster_token_proto_rawDescData +} + +var file_cluster_token_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_cluster_token_proto_goTypes = []interface{}{ + (*GenerateClusterTokenIn)(nil), // 0: GenerateClusterTokenIn + (*GenerateClusterTokenOut)(nil), // 1: GenerateClusterTokenOut + (*GetClusterTokenIn)(nil), // 2: GetClusterTokenIn + (*GetClusterTokenOut)(nil), // 3: GetClusterTokenOut +} +var file_cluster_token_proto_depIdxs = []int32{ + 0, // 0: ClusterToken.GenerateClusterToken:input_type -> GenerateClusterTokenIn + 2, // 1: ClusterToken.GetClusterToken:input_type -> GetClusterTokenIn + 1, // 2: ClusterToken.GenerateClusterToken:output_type -> GenerateClusterTokenOut + 3, // 3: ClusterToken.GetClusterToken:output_type -> GetClusterTokenOut + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_cluster_token_proto_init() } +func file_cluster_token_proto_init() { + if File_cluster_token_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cluster_token_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenerateClusterTokenIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_token_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenerateClusterTokenOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_token_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClusterTokenIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_token_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClusterTokenOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cluster_token_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_cluster_token_proto_goTypes, + DependencyIndexes: file_cluster_token_proto_depIdxs, + MessageInfos: file_cluster_token_proto_msgTypes, + }.Build() + File_cluster_token_proto = out.File + file_cluster_token_proto_rawDesc = nil + file_cluster_token_proto_goTypes = nil + file_cluster_token_proto_depIdxs = nil +} diff --git a/apps/message-office/protobufs/cluster-token/cluster-token_grpc.pb.go b/apps/message-office/protobufs/cluster-token/cluster-token_grpc.pb.go new file mode 100644 index 000000000..e51f7370e --- /dev/null +++ b/apps/message-office/protobufs/cluster-token/cluster-token_grpc.pb.go @@ -0,0 +1,146 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.24.4 +// source: cluster-token.proto + +package cluster_token + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + ClusterToken_GenerateClusterToken_FullMethodName = "/ClusterToken/GenerateClusterToken" + ClusterToken_GetClusterToken_FullMethodName = "/ClusterToken/GetClusterToken" +) + +// ClusterTokenClient is the client API for ClusterToken service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ClusterTokenClient interface { + GenerateClusterToken(ctx context.Context, in *GenerateClusterTokenIn, opts ...grpc.CallOption) (*GenerateClusterTokenOut, error) + GetClusterToken(ctx context.Context, in *GetClusterTokenIn, opts ...grpc.CallOption) (*GetClusterTokenOut, error) +} + +type clusterTokenClient struct { + cc grpc.ClientConnInterface +} + +func NewClusterTokenClient(cc grpc.ClientConnInterface) ClusterTokenClient { + return &clusterTokenClient{cc} +} + +func (c *clusterTokenClient) GenerateClusterToken(ctx context.Context, in *GenerateClusterTokenIn, opts ...grpc.CallOption) (*GenerateClusterTokenOut, error) { + out := new(GenerateClusterTokenOut) + err := c.cc.Invoke(ctx, ClusterToken_GenerateClusterToken_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *clusterTokenClient) GetClusterToken(ctx context.Context, in *GetClusterTokenIn, opts ...grpc.CallOption) (*GetClusterTokenOut, error) { + out := new(GetClusterTokenOut) + err := c.cc.Invoke(ctx, ClusterToken_GetClusterToken_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ClusterTokenServer is the server API for ClusterToken service. +// All implementations must embed UnimplementedClusterTokenServer +// for forward compatibility +type ClusterTokenServer interface { + GenerateClusterToken(context.Context, *GenerateClusterTokenIn) (*GenerateClusterTokenOut, error) + GetClusterToken(context.Context, *GetClusterTokenIn) (*GetClusterTokenOut, error) + mustEmbedUnimplementedClusterTokenServer() +} + +// UnimplementedClusterTokenServer must be embedded to have forward compatible implementations. +type UnimplementedClusterTokenServer struct { +} + +func (UnimplementedClusterTokenServer) GenerateClusterToken(context.Context, *GenerateClusterTokenIn) (*GenerateClusterTokenOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method GenerateClusterToken not implemented") +} +func (UnimplementedClusterTokenServer) GetClusterToken(context.Context, *GetClusterTokenIn) (*GetClusterTokenOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetClusterToken not implemented") +} +func (UnimplementedClusterTokenServer) mustEmbedUnimplementedClusterTokenServer() {} + +// UnsafeClusterTokenServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ClusterTokenServer will +// result in compilation errors. +type UnsafeClusterTokenServer interface { + mustEmbedUnimplementedClusterTokenServer() +} + +func RegisterClusterTokenServer(s grpc.ServiceRegistrar, srv ClusterTokenServer) { + s.RegisterService(&ClusterToken_ServiceDesc, srv) +} + +func _ClusterToken_GenerateClusterToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GenerateClusterTokenIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterTokenServer).GenerateClusterToken(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterToken_GenerateClusterToken_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterTokenServer).GenerateClusterToken(ctx, req.(*GenerateClusterTokenIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _ClusterToken_GetClusterToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetClusterTokenIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterTokenServer).GetClusterToken(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterToken_GetClusterToken_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterTokenServer).GetClusterToken(ctx, req.(*GetClusterTokenIn)) + } + return interceptor(ctx, in, info, handler) +} + +// ClusterToken_ServiceDesc is the grpc.ServiceDesc for ClusterToken service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ClusterToken_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "ClusterToken", + HandlerType: (*ClusterTokenServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GenerateClusterToken", + Handler: _ClusterToken_GenerateClusterToken_Handler, + }, + { + MethodName: "GetClusterToken", + Handler: _ClusterToken_GetClusterToken_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cluster-token.proto", +} diff --git a/apps/message-office/protobufs/platform-edge.proto b/apps/message-office/protobufs/platform-edge.proto new file mode 100644 index 000000000..6688634d4 --- /dev/null +++ b/apps/message-office/protobufs/platform-edge.proto @@ -0,0 +1,36 @@ +syntax = "proto3"; + +option go_package = "./platform-edge"; + +service PlatformEdge { + rpc ListPlatformEdgeClusters(ListPlatformEdgeClustersIn) returns (ListPlatformEdgeClustersOut); + rpc AllocatePlatformEdgeCluster(AllocatePlatformEdgeClusterIn) returns (AllocatePlatformEdgeClusterOut); + rpc GetAllocatedPlatformEdgeCluster(GetAllocatedPlatformEdgeClusterIn) returns (AllocatePlatformEdgeClusterOut); +} + +message ListPlatformEdgeClustersIn { + string region = 1; +} + +message PlatformEdgeCluster { + string region = 1; + string cluster_name = 2; +} + +message ListPlatformEdgeClustersOut { + repeated PlatformEdgeCluster platform_edge_clusters = 1; +} + +message AllocatePlatformEdgeClusterIn { + string region = 1; + string account_name = 2; +} + +message AllocatePlatformEdgeClusterOut { + string cluster_name = 1; + string owned_by_account = 2; +} + +message GetAllocatedPlatformEdgeClusterIn { + string account_name = 1; +} diff --git a/apps/message-office/protobufs/platform-edge/platform-edge.pb.go b/apps/message-office/protobufs/platform-edge/platform-edge.pb.go new file mode 100644 index 000000000..9ea255aa9 --- /dev/null +++ b/apps/message-office/protobufs/platform-edge/platform-edge.pb.go @@ -0,0 +1,522 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.24.4 +// source: platform-edge.proto + +package platform_edge + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ListPlatformEdgeClustersIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` +} + +func (x *ListPlatformEdgeClustersIn) Reset() { + *x = ListPlatformEdgeClustersIn{} + if protoimpl.UnsafeEnabled { + mi := &file_platform_edge_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPlatformEdgeClustersIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPlatformEdgeClustersIn) ProtoMessage() {} + +func (x *ListPlatformEdgeClustersIn) ProtoReflect() protoreflect.Message { + mi := &file_platform_edge_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPlatformEdgeClustersIn.ProtoReflect.Descriptor instead. +func (*ListPlatformEdgeClustersIn) Descriptor() ([]byte, []int) { + return file_platform_edge_proto_rawDescGZIP(), []int{0} +} + +func (x *ListPlatformEdgeClustersIn) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +type PlatformEdgeCluster struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` + ClusterName string `protobuf:"bytes,2,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` +} + +func (x *PlatformEdgeCluster) Reset() { + *x = PlatformEdgeCluster{} + if protoimpl.UnsafeEnabled { + mi := &file_platform_edge_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PlatformEdgeCluster) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PlatformEdgeCluster) ProtoMessage() {} + +func (x *PlatformEdgeCluster) ProtoReflect() protoreflect.Message { + mi := &file_platform_edge_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PlatformEdgeCluster.ProtoReflect.Descriptor instead. +func (*PlatformEdgeCluster) Descriptor() ([]byte, []int) { + return file_platform_edge_proto_rawDescGZIP(), []int{1} +} + +func (x *PlatformEdgeCluster) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *PlatformEdgeCluster) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +type ListPlatformEdgeClustersOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PlatformEdgeClusters []*PlatformEdgeCluster `protobuf:"bytes,1,rep,name=platform_edge_clusters,json=platformEdgeClusters,proto3" json:"platform_edge_clusters,omitempty"` +} + +func (x *ListPlatformEdgeClustersOut) Reset() { + *x = ListPlatformEdgeClustersOut{} + if protoimpl.UnsafeEnabled { + mi := &file_platform_edge_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPlatformEdgeClustersOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPlatformEdgeClustersOut) ProtoMessage() {} + +func (x *ListPlatformEdgeClustersOut) ProtoReflect() protoreflect.Message { + mi := &file_platform_edge_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListPlatformEdgeClustersOut.ProtoReflect.Descriptor instead. +func (*ListPlatformEdgeClustersOut) Descriptor() ([]byte, []int) { + return file_platform_edge_proto_rawDescGZIP(), []int{2} +} + +func (x *ListPlatformEdgeClustersOut) GetPlatformEdgeClusters() []*PlatformEdgeCluster { + if x != nil { + return x.PlatformEdgeClusters + } + return nil +} + +type AllocatePlatformEdgeClusterIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Region string `protobuf:"bytes,1,opt,name=region,proto3" json:"region,omitempty"` + AccountName string `protobuf:"bytes,2,opt,name=account_name,json=accountName,proto3" json:"account_name,omitempty"` +} + +func (x *AllocatePlatformEdgeClusterIn) Reset() { + *x = AllocatePlatformEdgeClusterIn{} + if protoimpl.UnsafeEnabled { + mi := &file_platform_edge_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AllocatePlatformEdgeClusterIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllocatePlatformEdgeClusterIn) ProtoMessage() {} + +func (x *AllocatePlatformEdgeClusterIn) ProtoReflect() protoreflect.Message { + mi := &file_platform_edge_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllocatePlatformEdgeClusterIn.ProtoReflect.Descriptor instead. +func (*AllocatePlatformEdgeClusterIn) Descriptor() ([]byte, []int) { + return file_platform_edge_proto_rawDescGZIP(), []int{3} +} + +func (x *AllocatePlatformEdgeClusterIn) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *AllocatePlatformEdgeClusterIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +type AllocatePlatformEdgeClusterOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterName string `protobuf:"bytes,1,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` + OwnedByAccount string `protobuf:"bytes,2,opt,name=owned_by_account,json=ownedByAccount,proto3" json:"owned_by_account,omitempty"` +} + +func (x *AllocatePlatformEdgeClusterOut) Reset() { + *x = AllocatePlatformEdgeClusterOut{} + if protoimpl.UnsafeEnabled { + mi := &file_platform_edge_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AllocatePlatformEdgeClusterOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllocatePlatformEdgeClusterOut) ProtoMessage() {} + +func (x *AllocatePlatformEdgeClusterOut) ProtoReflect() protoreflect.Message { + mi := &file_platform_edge_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllocatePlatformEdgeClusterOut.ProtoReflect.Descriptor instead. +func (*AllocatePlatformEdgeClusterOut) Descriptor() ([]byte, []int) { + return file_platform_edge_proto_rawDescGZIP(), []int{4} +} + +func (x *AllocatePlatformEdgeClusterOut) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +func (x *AllocatePlatformEdgeClusterOut) GetOwnedByAccount() string { + if x != nil { + return x.OwnedByAccount + } + return "" +} + +type GetAllocatedPlatformEdgeClusterIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccountName string `protobuf:"bytes,1,opt,name=account_name,json=accountName,proto3" json:"account_name,omitempty"` +} + +func (x *GetAllocatedPlatformEdgeClusterIn) Reset() { + *x = GetAllocatedPlatformEdgeClusterIn{} + if protoimpl.UnsafeEnabled { + mi := &file_platform_edge_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetAllocatedPlatformEdgeClusterIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAllocatedPlatformEdgeClusterIn) ProtoMessage() {} + +func (x *GetAllocatedPlatformEdgeClusterIn) ProtoReflect() protoreflect.Message { + mi := &file_platform_edge_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetAllocatedPlatformEdgeClusterIn.ProtoReflect.Descriptor instead. +func (*GetAllocatedPlatformEdgeClusterIn) Descriptor() ([]byte, []int) { + return file_platform_edge_proto_rawDescGZIP(), []int{5} +} + +func (x *GetAllocatedPlatformEdgeClusterIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +var File_platform_edge_proto protoreflect.FileDescriptor + +var file_platform_edge_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x73, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x13, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x69, 0x0a, + 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, + 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x4f, 0x75, 0x74, 0x12, 0x4a, 0x0a, 0x16, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x65, 0x64, 0x67, 0x65, 0x5f, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x52, 0x14, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x22, 0x5a, 0x0a, 0x1d, 0x41, 0x6c, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x6d, 0x0a, 0x1e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, + 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x77, 0x6e, + 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x42, 0x79, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x32, 0xad, 0x02, 0x0a, 0x0c, + 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x12, 0x55, 0x0a, 0x18, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x73, 0x49, 0x6e, 0x1a, 0x1c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, + 0x4f, 0x75, 0x74, 0x12, 0x5e, 0x0a, 0x1b, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x49, 0x6e, 0x1a, 0x1f, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x4f, 0x75, 0x74, 0x12, 0x66, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, + 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x1a, 0x1f, 0x2e, 0x41, 0x6c, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, + 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x42, 0x11, 0x5a, 0x0f, 0x2e, + 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_platform_edge_proto_rawDescOnce sync.Once + file_platform_edge_proto_rawDescData = file_platform_edge_proto_rawDesc +) + +func file_platform_edge_proto_rawDescGZIP() []byte { + file_platform_edge_proto_rawDescOnce.Do(func() { + file_platform_edge_proto_rawDescData = protoimpl.X.CompressGZIP(file_platform_edge_proto_rawDescData) + }) + return file_platform_edge_proto_rawDescData +} + +var file_platform_edge_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_platform_edge_proto_goTypes = []interface{}{ + (*ListPlatformEdgeClustersIn)(nil), // 0: ListPlatformEdgeClustersIn + (*PlatformEdgeCluster)(nil), // 1: PlatformEdgeCluster + (*ListPlatformEdgeClustersOut)(nil), // 2: ListPlatformEdgeClustersOut + (*AllocatePlatformEdgeClusterIn)(nil), // 3: AllocatePlatformEdgeClusterIn + (*AllocatePlatformEdgeClusterOut)(nil), // 4: AllocatePlatformEdgeClusterOut + (*GetAllocatedPlatformEdgeClusterIn)(nil), // 5: GetAllocatedPlatformEdgeClusterIn +} +var file_platform_edge_proto_depIdxs = []int32{ + 1, // 0: ListPlatformEdgeClustersOut.platform_edge_clusters:type_name -> PlatformEdgeCluster + 0, // 1: PlatformEdge.ListPlatformEdgeClusters:input_type -> ListPlatformEdgeClustersIn + 3, // 2: PlatformEdge.AllocatePlatformEdgeCluster:input_type -> AllocatePlatformEdgeClusterIn + 5, // 3: PlatformEdge.GetAllocatedPlatformEdgeCluster:input_type -> GetAllocatedPlatformEdgeClusterIn + 2, // 4: PlatformEdge.ListPlatformEdgeClusters:output_type -> ListPlatformEdgeClustersOut + 4, // 5: PlatformEdge.AllocatePlatformEdgeCluster:output_type -> AllocatePlatformEdgeClusterOut + 4, // 6: PlatformEdge.GetAllocatedPlatformEdgeCluster:output_type -> AllocatePlatformEdgeClusterOut + 4, // [4:7] is the sub-list for method output_type + 1, // [1:4] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_platform_edge_proto_init() } +func file_platform_edge_proto_init() { + if File_platform_edge_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_platform_edge_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPlatformEdgeClustersIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_platform_edge_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PlatformEdgeCluster); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_platform_edge_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPlatformEdgeClustersOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_platform_edge_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AllocatePlatformEdgeClusterIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_platform_edge_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AllocatePlatformEdgeClusterOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_platform_edge_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetAllocatedPlatformEdgeClusterIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_platform_edge_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_platform_edge_proto_goTypes, + DependencyIndexes: file_platform_edge_proto_depIdxs, + MessageInfos: file_platform_edge_proto_msgTypes, + }.Build() + File_platform_edge_proto = out.File + file_platform_edge_proto_rawDesc = nil + file_platform_edge_proto_goTypes = nil + file_platform_edge_proto_depIdxs = nil +} diff --git a/apps/message-office/protobufs/platform-edge/platform-edge_grpc.pb.go b/apps/message-office/protobufs/platform-edge/platform-edge_grpc.pb.go new file mode 100644 index 000000000..086a6e1bd --- /dev/null +++ b/apps/message-office/protobufs/platform-edge/platform-edge_grpc.pb.go @@ -0,0 +1,183 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.24.4 +// source: platform-edge.proto + +package platform_edge + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + PlatformEdge_ListPlatformEdgeClusters_FullMethodName = "/PlatformEdge/ListPlatformEdgeClusters" + PlatformEdge_AllocatePlatformEdgeCluster_FullMethodName = "/PlatformEdge/AllocatePlatformEdgeCluster" + PlatformEdge_GetAllocatedPlatformEdgeCluster_FullMethodName = "/PlatformEdge/GetAllocatedPlatformEdgeCluster" +) + +// PlatformEdgeClient is the client API for PlatformEdge service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PlatformEdgeClient interface { + ListPlatformEdgeClusters(ctx context.Context, in *ListPlatformEdgeClustersIn, opts ...grpc.CallOption) (*ListPlatformEdgeClustersOut, error) + AllocatePlatformEdgeCluster(ctx context.Context, in *AllocatePlatformEdgeClusterIn, opts ...grpc.CallOption) (*AllocatePlatformEdgeClusterOut, error) + GetAllocatedPlatformEdgeCluster(ctx context.Context, in *GetAllocatedPlatformEdgeClusterIn, opts ...grpc.CallOption) (*AllocatePlatformEdgeClusterOut, error) +} + +type platformEdgeClient struct { + cc grpc.ClientConnInterface +} + +func NewPlatformEdgeClient(cc grpc.ClientConnInterface) PlatformEdgeClient { + return &platformEdgeClient{cc} +} + +func (c *platformEdgeClient) ListPlatformEdgeClusters(ctx context.Context, in *ListPlatformEdgeClustersIn, opts ...grpc.CallOption) (*ListPlatformEdgeClustersOut, error) { + out := new(ListPlatformEdgeClustersOut) + err := c.cc.Invoke(ctx, PlatformEdge_ListPlatformEdgeClusters_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *platformEdgeClient) AllocatePlatformEdgeCluster(ctx context.Context, in *AllocatePlatformEdgeClusterIn, opts ...grpc.CallOption) (*AllocatePlatformEdgeClusterOut, error) { + out := new(AllocatePlatformEdgeClusterOut) + err := c.cc.Invoke(ctx, PlatformEdge_AllocatePlatformEdgeCluster_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *platformEdgeClient) GetAllocatedPlatformEdgeCluster(ctx context.Context, in *GetAllocatedPlatformEdgeClusterIn, opts ...grpc.CallOption) (*AllocatePlatformEdgeClusterOut, error) { + out := new(AllocatePlatformEdgeClusterOut) + err := c.cc.Invoke(ctx, PlatformEdge_GetAllocatedPlatformEdgeCluster_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PlatformEdgeServer is the server API for PlatformEdge service. +// All implementations must embed UnimplementedPlatformEdgeServer +// for forward compatibility +type PlatformEdgeServer interface { + ListPlatformEdgeClusters(context.Context, *ListPlatformEdgeClustersIn) (*ListPlatformEdgeClustersOut, error) + AllocatePlatformEdgeCluster(context.Context, *AllocatePlatformEdgeClusterIn) (*AllocatePlatformEdgeClusterOut, error) + GetAllocatedPlatformEdgeCluster(context.Context, *GetAllocatedPlatformEdgeClusterIn) (*AllocatePlatformEdgeClusterOut, error) + mustEmbedUnimplementedPlatformEdgeServer() +} + +// UnimplementedPlatformEdgeServer must be embedded to have forward compatible implementations. +type UnimplementedPlatformEdgeServer struct { +} + +func (UnimplementedPlatformEdgeServer) ListPlatformEdgeClusters(context.Context, *ListPlatformEdgeClustersIn) (*ListPlatformEdgeClustersOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListPlatformEdgeClusters not implemented") +} +func (UnimplementedPlatformEdgeServer) AllocatePlatformEdgeCluster(context.Context, *AllocatePlatformEdgeClusterIn) (*AllocatePlatformEdgeClusterOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method AllocatePlatformEdgeCluster not implemented") +} +func (UnimplementedPlatformEdgeServer) GetAllocatedPlatformEdgeCluster(context.Context, *GetAllocatedPlatformEdgeClusterIn) (*AllocatePlatformEdgeClusterOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAllocatedPlatformEdgeCluster not implemented") +} +func (UnimplementedPlatformEdgeServer) mustEmbedUnimplementedPlatformEdgeServer() {} + +// UnsafePlatformEdgeServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PlatformEdgeServer will +// result in compilation errors. +type UnsafePlatformEdgeServer interface { + mustEmbedUnimplementedPlatformEdgeServer() +} + +func RegisterPlatformEdgeServer(s grpc.ServiceRegistrar, srv PlatformEdgeServer) { + s.RegisterService(&PlatformEdge_ServiceDesc, srv) +} + +func _PlatformEdge_ListPlatformEdgeClusters_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListPlatformEdgeClustersIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PlatformEdgeServer).ListPlatformEdgeClusters(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PlatformEdge_ListPlatformEdgeClusters_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PlatformEdgeServer).ListPlatformEdgeClusters(ctx, req.(*ListPlatformEdgeClustersIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _PlatformEdge_AllocatePlatformEdgeCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AllocatePlatformEdgeClusterIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PlatformEdgeServer).AllocatePlatformEdgeCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PlatformEdge_AllocatePlatformEdgeCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PlatformEdgeServer).AllocatePlatformEdgeCluster(ctx, req.(*AllocatePlatformEdgeClusterIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _PlatformEdge_GetAllocatedPlatformEdgeCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAllocatedPlatformEdgeClusterIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PlatformEdgeServer).GetAllocatedPlatformEdgeCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PlatformEdge_GetAllocatedPlatformEdgeCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PlatformEdgeServer).GetAllocatedPlatformEdgeCluster(ctx, req.(*GetAllocatedPlatformEdgeClusterIn)) + } + return interceptor(ctx, in, info, handler) +} + +// PlatformEdge_ServiceDesc is the grpc.ServiceDesc for PlatformEdge service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PlatformEdge_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "PlatformEdge", + HandlerType: (*PlatformEdgeServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListPlatformEdgeClusters", + Handler: _PlatformEdge_ListPlatformEdgeClusters_Handler, + }, + { + MethodName: "AllocatePlatformEdgeCluster", + Handler: _PlatformEdge_AllocatePlatformEdgeCluster_Handler, + }, + { + MethodName: "GetAllocatedPlatformEdgeCluster", + Handler: _PlatformEdge_GetAllocatedPlatformEdgeCluster_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "platform-edge.proto", +} diff --git a/apps/message-office/types/errors.go b/apps/message-office/types/errors.go new file mode 100644 index 000000000..ab1254f4c --- /dev/null +++ b/apps/message-office/types/errors.go @@ -0,0 +1 @@ +package types diff --git a/apps/tenant-agent/main.go b/apps/tenant-agent/main.go index 724159f61..0df7629d5 100644 --- a/apps/tenant-agent/main.go +++ b/apps/tenant-agent/main.go @@ -106,13 +106,6 @@ func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) er switch msg.Action { case t.ActionApply: { - ann := obj.GetAnnotations() - if ann == nil { - ann = make(map[string]string, 2) - } - - obj.SetAnnotations(ann) - b, err := yaml.Marshal(msg.Object) if err != nil { return g.handleErrorOnApply(ctx, err, msg) diff --git a/mocks/pkg/k8s/client.go b/mocks/pkg/k8s/client.go index 434db7138..c8c204ca2 100644 --- a/mocks/pkg/k8s/client.go +++ b/mocks/pkg/k8s/client.go @@ -21,7 +21,7 @@ type Client struct { MockDeleteYAML func(ctx context.Context, yamls ...[]byte) error MockGet func(ctx context.Context, nn types.NamespacedName, obj client.Object) error MockList func(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error - MockListSecrets func(ctx context.Context, namespace string, secretType corev1.SecretType) ([]v1.Secret, error) + MockListSecrets func(ctx context.Context, namespace string, secretType corev1.SecretType) ([]corev1.Secret, error) MockReadLogs func(ctx context.Context, namespace string, name string, writer io.WriteCloser, opts *k8s.ReadLogsOptions) error MockUpdate func(ctx context.Context, obj client.Object) error MockValidateObject func(ctx context.Context, obj client.Object) error @@ -82,7 +82,7 @@ func (cMock *Client) List(ctx context.Context, list client.ObjectList, opts ...c panic("Client: method 'List' not implemented, yet") } -func (cMock *Client) ListSecrets(ctx context.Context, namespace string, secretType corev1.SecretType) ([]v1.Secret, error) { +func (cMock *Client) ListSecrets(ctx context.Context, namespace string, secretType corev1.SecretType) ([]corev1.Secret, error) { if cMock.MockListSecrets != nil { cMock.registerCall("ListSecrets", ctx, namespace, secretType) return cMock.MockListSecrets(ctx, namespace, secretType) diff --git a/mocks/pkg/repos/dbrepo.go b/mocks/pkg/repos/dbrepo.go index 46d0247cc..b94162032 100644 --- a/mocks/pkg/repos/dbrepo.go +++ b/mocks/pkg/repos/dbrepo.go @@ -23,8 +23,9 @@ type DbRepo[T repos.Entity] struct { MockFindById func(ctx context.Context, id repos.ID) (T, error) MockFindOne func(ctx context.Context, filter repos.Filter) (T, error) MockFindPaginated func(ctx context.Context, filter repos.Filter, pagination repos.CursorPagination) (*repos.PaginatedRecord[T], error) + MockGroupByAndCount func(ctx context.Context, filter repos.Filter, groupBy string, opts repos.GroupByAndCountOptions) (map[string]int64, error) MockIndexFields func(ctx context.Context, indices []repos.IndexField) error - MockMergeMatchFilters func(filter repos.Filter, matchFilters map[string]repos.MatchFilter) repos.Filter + MockMergeMatchFilters func(filter repos.Filter, matchFilters ...map[string]repos.MatchFilter) repos.Filter MockNewId func() repos.ID MockPatch func(ctx context.Context, filter repos.Filter, patch repos.Document, opts ...repos.UpdateOpts) (T, error) MockPatchById func(ctx context.Context, id repos.ID, patch repos.Document, opts ...repos.UpdateOpts) (T, error) @@ -139,6 +140,14 @@ func (dMock *DbRepo[T]) FindPaginated(ctx context.Context, filter repos.Filter, panic("DbRepo[T]: method 'FindPaginated' not implemented, yet") } +func (dMock *DbRepo[T]) GroupByAndCount(ctx context.Context, filter repos.Filter, groupBy string, opts repos.GroupByAndCountOptions) (map[string]int64, error) { + if dMock.MockGroupByAndCount != nil { + dMock.registerCall("GroupByAndCount", ctx, filter, groupBy, opts) + return dMock.MockGroupByAndCount(ctx, filter, groupBy, opts) + } + panic("DbRepo[T]: method 'GroupByAndCount' not implemented, yet") +} + func (dMock *DbRepo[T]) IndexFields(ctx context.Context, indices []repos.IndexField) error { if dMock.MockIndexFields != nil { dMock.registerCall("IndexFields", ctx, indices) @@ -147,10 +156,10 @@ func (dMock *DbRepo[T]) IndexFields(ctx context.Context, indices []repos.IndexFi panic("DbRepo[T]: method 'IndexFields' not implemented, yet") } -func (dMock *DbRepo[T]) MergeMatchFilters(filter repos.Filter, matchFilters map[string]repos.MatchFilter) repos.Filter { +func (dMock *DbRepo[T]) MergeMatchFilters(filter repos.Filter, matchFilters ...map[string]repos.MatchFilter) repos.Filter { if dMock.MockMergeMatchFilters != nil { dMock.registerCall("MergeMatchFilters", filter, matchFilters) - return dMock.MockMergeMatchFilters(filter, matchFilters) + return dMock.MockMergeMatchFilters(filter, matchFilters...) } panic("DbRepo[T]: method 'MergeMatchFilters' not implemented, yet") } diff --git a/pkg/logging/slog-logger.go b/pkg/logging/slog-logger.go index 2b220328a..f2a5a9309 100644 --- a/pkg/logging/slog-logger.go +++ b/pkg/logging/slog-logger.go @@ -43,6 +43,8 @@ func NewSlogLogger(opts SlogOptions) *slog.Logger { }) styles := log.DefaultStyles() + // styles.Caller = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Dark: "#5b717f", Light: "#36cbfa"}).Faint(true) + styles.Caller = lipgloss.NewStyle().Foreground(lipgloss.Color("#878a8a")) styles.Levels[log.DebugLevel] = styles.Levels[log.DebugLevel].Foreground(lipgloss.Color("#5b717f")) styles.Levels[log.InfoLevel] = styles.Levels[log.InfoLevel].Foreground(lipgloss.Color("#36cbfa")) diff --git a/pkg/repos/db-repo-mongo.go b/pkg/repos/db-repo-mongo.go index e5b2082a1..d9165fc1b 100644 --- a/pkg/repos/db-repo-mongo.go +++ b/pkg/repos/db-repo-mongo.go @@ -696,6 +696,46 @@ func (repo *dbRepo[T]) MergeMatchFilters(filter Filter, matchFilters ...map[stri return filter } +type GroupByAndCountOptions struct { + Limit int64 + Sort SortDirection +} + +func (repo *dbRepo[T]) GroupByAndCount(ctx context.Context, filter Filter, groupBy string, opts GroupByAndCountOptions) (map[string]int64, error) { + agg := make([]bson.M, 0, 4) + if filter != nil { + agg = append(agg, bson.M{"$match": filter}) + } + + agg = append(agg, + bson.M{ + "$group": bson.M{ + "_id": "$" + groupBy, + "count": bson.M{"$sum": 1}, + }, + }, + bson.M{"$sort": bson.M{"count": opts.Sort.Int()}}, + bson.M{"$limit": opts.Limit}, + ) + + records, err := repo.db.Collection(repo.collectionName).Aggregate(ctx, agg) + if err != nil { + return nil, errors.NewE(err) + } + + var data []bson.M + if err := records.Decode(&data); err != nil { + return nil, errors.NewE(err) + } + + result := make(map[string]int64, len(data)) + for _, v := range data { + result[v["_id"].(string)] = v["count"].(int64) + } + + return result, nil +} + type MongoRepoOptions struct { IndexFields []string } diff --git a/pkg/repos/db-repo.go b/pkg/repos/db-repo.go index 2a45911ee..3b4dd045c 100644 --- a/pkg/repos/db-repo.go +++ b/pkg/repos/db-repo.go @@ -114,6 +114,8 @@ type DbRepo[T Entity] interface { // Delete(ctx context.Context, query Query) ([]ID, error) DeleteOne(ctx context.Context, filter Filter) error + GroupByAndCount(ctx context.Context, filter Filter, groupBy string, opts GroupByAndCountOptions) (map[string]int64, error) + ErrAlreadyExists(err error) bool MergeMatchFilters(filter Filter, matchFilters ...map[string]MatchFilter) Filter } @@ -172,6 +174,13 @@ const ( SortDirectionDesc SortDirection = "DESC" ) +func (s SortDirection) Int() int64 { + if s == SortDirectionAsc { + return 1 + } + return -1 +} + var DefaultCursorPagination = CursorPagination{ First: functions.New(int64(10)), After: nil, diff --git a/pkg/repos/mongo.go b/pkg/repos/mongo.go index 74ebbc9b4..44df61bf2 100644 --- a/pkg/repos/mongo.go +++ b/pkg/repos/mongo.go @@ -17,6 +17,7 @@ func NewMongoDatabase(ctx context.Context, uri string, dbName string) (db *mongo if err != nil { return nil, errors.NewEf(err, "could not connect to mongodb servers") } + return client.Database(dbName), nil } From 144ab0538a14be822c7ce4d755f16a8f5f20ba0d Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Thu, 5 Sep 2024 14:49:29 +0530 Subject: [PATCH 02/17] feat(grpc): adds support for custom grpc errors parsing --- pkg/grpc/Taskfile.yml | 6 ++ pkg/grpc/errors.go | 33 ++++++++ pkg/grpc/errors.proto | 8 ++ pkg/grpc/errors/errors.pb.go | 151 +++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 pkg/grpc/Taskfile.yml create mode 100644 pkg/grpc/errors.go create mode 100644 pkg/grpc/errors.proto create mode 100644 pkg/grpc/errors/errors.pb.go diff --git a/pkg/grpc/Taskfile.yml b/pkg/grpc/Taskfile.yml new file mode 100644 index 000000000..3f6ec790d --- /dev/null +++ b/pkg/grpc/Taskfile.yml @@ -0,0 +1,6 @@ +version: 3 + +tasks: + build: + cmds: + - protoc --go_out=. --go-grpc_out=. --go_opt=paths=import --go-grpc_opt=paths=import ./*.proto diff --git a/pkg/grpc/errors.go b/pkg/grpc/errors.go new file mode 100644 index 000000000..c9ce66182 --- /dev/null +++ b/pkg/grpc/errors.go @@ -0,0 +1,33 @@ +package grpc + +import ( + "strings" + + "github.com/kloudlite/api/pkg/grpc/errors" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func Err(err error, comments ...string) error { + s := status.New(codes.Unknown, err.Error()) + s2, e := s.WithDetails(&errors.Error{ + Message: err.Error(), + Comments: strings.Join(comments, "\n"), + }) + if e != nil { + panic(e) + } + return s2.Err() +} + +func ParseErr(err error) *errors.Error { + s := status.Convert(err) + for _, detail := range s.Details() { + e, ok := detail.(*errors.Error) + if !ok { + continue + } + return e + } + return nil +} diff --git a/pkg/grpc/errors.proto b/pkg/grpc/errors.proto new file mode 100644 index 000000000..a0401c302 --- /dev/null +++ b/pkg/grpc/errors.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +option go_package = "./errors"; + +message Error { + string message = 1; + string comments = 2; +} diff --git a/pkg/grpc/errors/errors.pb.go b/pkg/grpc/errors/errors.pb.go new file mode 100644 index 000000000..01ecb406b --- /dev/null +++ b/pkg/grpc/errors/errors.pb.go @@ -0,0 +1,151 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.24.4 +// source: errors.proto + +package errors + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Error struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Comments string `protobuf:"bytes,2,opt,name=comments,proto3" json:"comments,omitempty"` +} + +func (x *Error) Reset() { + *x = Error{} + if protoimpl.UnsafeEnabled { + mi := &file_errors_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Error) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Error) ProtoMessage() {} + +func (x *Error) ProtoReflect() protoreflect.Message { + mi := &file_errors_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Error.ProtoReflect.Descriptor instead. +func (*Error) Descriptor() ([]byte, []int) { + return file_errors_proto_rawDescGZIP(), []int{0} +} + +func (x *Error) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *Error) GetComments() string { + if x != nil { + return x.Comments + } + return "" +} + +var File_errors_proto protoreflect.FileDescriptor + +var file_errors_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3d, + 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x5a, + 0x08, 0x2e, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_errors_proto_rawDescOnce sync.Once + file_errors_proto_rawDescData = file_errors_proto_rawDesc +) + +func file_errors_proto_rawDescGZIP() []byte { + file_errors_proto_rawDescOnce.Do(func() { + file_errors_proto_rawDescData = protoimpl.X.CompressGZIP(file_errors_proto_rawDescData) + }) + return file_errors_proto_rawDescData +} + +var file_errors_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_errors_proto_goTypes = []interface{}{ + (*Error)(nil), // 0: Error +} +var file_errors_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_errors_proto_init() } +func file_errors_proto_init() { + if File_errors_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_errors_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Error); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_errors_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_errors_proto_goTypes, + DependencyIndexes: file_errors_proto_depIdxs, + MessageInfos: file_errors_proto_msgTypes, + }.Build() + File_errors_proto = out.File + file_errors_proto_rawDesc = nil + file_errors_proto_goTypes = nil + file_errors_proto_depIdxs = nil +} From 1e0a79f279e1595386600ad379aeb96d9644547e Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Thu, 5 Sep 2024 14:52:38 +0530 Subject: [PATCH 03/17] fix(mongo): fixes mongodb groupByAndCount result parsing --- common/banner.go | 40 ++++++++++++++++++++++++++++++++++---- pkg/repos/db-repo-mongo.go | 10 +++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/common/banner.go b/common/banner.go index 713606929..b747e5a0d 100644 --- a/common/banner.go +++ b/common/banner.go @@ -1,6 +1,9 @@ package common -import "fmt" +import ( + "fmt" + "time" +) var BuiltAt string @@ -9,17 +12,17 @@ const KloudliteReadyBanner = ` ##### ######## ######## - ######## ##### + ######## ##### ######## *######### ██╗ ██╗██╗ ██████╗ ██╗ ██╗██████╗ ██╗ ██╗████████╗███████╗ ######## ############### ██║ ██╔╝██║ ██╔═══██╗██║ ██║██╔══██╗██║ ██║╚══██╔══╝██╔════╝ ######## *################### █████╔╝ ██║ ██║ ██║██║ ██║██║ ██║██║ ██║ ██║ █████╗ #######/ ######################## ██╔═██╗ ██║ ██║ ██║██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ #######( ################### ██║ ██╗███████╗╚██████╔╝╚██████╔╝██████╔╝███████╗██║ ██║ ███████╗ (#######. ##############* ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝ - ######## #(####### + ######## #(####### BuiltAt: %s (#######. ####* __ ___ __ ######## |__) |__ /\ | \ \ / - /######(. | \ |___ /~~\ |__/ | BuiltAt: %s + /######(. | \ |___ /~~\ |__/ | ##### , @@ -53,3 +56,32 @@ const KloudliteBanner = ` func PrintKloudliteBanner() { fmt.Printf(KloudliteBanner, BuiltAt) } + +func PrintReadyBanner2(readyIn time.Duration) { + fmt.Printf(` + , + ##### + ######## + ######## + ######## ##### + ######## *######### ██╗ ██╗██╗ ██████╗ ██╗ ██╗██████╗ ██╗ ██╗████████╗███████╗ + ######## ############### ██║ ██╔╝██║ ██╔═══██╗██║ ██║██╔══██╗██║ ██║╚══██╔══╝██╔════╝ + ######## *################### █████╔╝ ██║ ██║ ██║██║ ██║██║ ██║██║ ██║ ██║ █████╗ + #######/ ######################## ██╔═██╗ ██║ ██║ ██║██║ ██║██║ ██║██║ ██║ ██║ ██╔══╝ + #######( ################### ██║ ██╗███████╗╚██████╔╝╚██████╔╝██████╔╝███████╗██║ ██║ ███████╗ + (#######. ##############* ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝ + ######## #(####### + (#######. ####* + ######## 🚀 running in %.2fs + /######(. + ##### + , + +`, readyIn.Seconds()) +} + +func PrintBuildInfo() { + fmt.Printf(` +📦 built at %s + `, BuiltAt) +} diff --git a/pkg/repos/db-repo-mongo.go b/pkg/repos/db-repo-mongo.go index d9165fc1b..0735473a3 100644 --- a/pkg/repos/db-repo-mongo.go +++ b/pkg/repos/db-repo-mongo.go @@ -724,12 +724,20 @@ func (repo *dbRepo[T]) GroupByAndCount(ctx context.Context, filter Filter, group } var data []bson.M - if err := records.Decode(&data); err != nil { + if err := records.All(ctx, &data); err != nil { return nil, errors.NewE(err) } + // var data bson.D + // if err := records.Decode(&data); err != nil { + // return nil, errors.NewE(err) + // } + result := make(map[string]int64, len(data)) for _, v := range data { + // m := v.Value.(map[string]any) + // result[m["_id"].(string)] = m["count"].(int64) + // v.Value.(map[string]interface{})["_id"] = v.Key result[v["_id"].(string)] = v["count"].(int64) } From 51b111d6858cbe2b331e36e198353bbcad5d0dbe Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Thu, 5 Sep 2024 17:53:06 +0530 Subject: [PATCH 04/17] feat(message-office): adds platform edge clusters support --- .../internal/app/internal-grpc-server.go | 10 +++++-- .../internal/app/vector-proxy-server.go | 6 ++++- apps/message-office/internal/domain/domain.go | 13 +++++++--- .../internal/domain/platform-edge/repo.go | 18 ++++++------- apps/message-office/main.go | 26 +++++++------------ 5 files changed, 41 insertions(+), 32 deletions(-) diff --git a/apps/message-office/internal/app/internal-grpc-server.go b/apps/message-office/internal/app/internal-grpc-server.go index 42c5da560..59eeb4ded 100644 --- a/apps/message-office/internal/app/internal-grpc-server.go +++ b/apps/message-office/internal/app/internal-grpc-server.go @@ -3,6 +3,7 @@ package app import ( "context" + mo_errors "github.com/kloudlite/api/apps/message-office/errors" "github.com/kloudlite/api/apps/message-office/internal/domain" cluster_token "github.com/kloudlite/api/apps/message-office/protobufs/cluster-token" platform_edge "github.com/kloudlite/api/apps/message-office/protobufs/platform-edge" @@ -16,7 +17,6 @@ type ( type internalServer struct { d domain.Domain - // message_office_internal.UnimplementedMessageOfficeInternalServer cluster_token.UnimplementedClusterTokenServer platform_edge.UnimplementedPlatformEdgeServer } @@ -47,13 +47,19 @@ func (s *internalServer) AllocatePlatformEdgeCluster(ctx context.Context, in *pl return nil, errors.NewE(err) } - return &platform_edge.AllocatePlatformEdgeClusterOut{ClusterName: pec.Name}, nil + return &platform_edge.AllocatePlatformEdgeClusterOut{ + ClusterName: pec.Name, + OwnedByAccount: pec.OwnedByAccount, + }, nil } // GetAllocatedPlatformEdgeCluster implements platform_edge.PlatformEdgeServer. func (s *internalServer) GetAllocatedPlatformEdgeCluster(ctx context.Context, in *platform_edge.GetAllocatedPlatformEdgeClusterIn) (*platform_edge.AllocatePlatformEdgeClusterOut, error) { allocated, err := s.d.GetAllocatedPlatformEdgeCluster(ctx, in.AccountName) if err != nil { + if errors.Is(err, mo_errors.ErrEdgeClusterNotAllocated) { + return nil, grpc.Err(mo_errors.ErrEdgeClusterNotAllocated) + } return nil, errors.NewE(err) } diff --git a/apps/message-office/internal/app/vector-proxy-server.go b/apps/message-office/internal/app/vector-proxy-server.go index a2f93a408..0a3b8acc5 100644 --- a/apps/message-office/internal/app/vector-proxy-server.go +++ b/apps/message-office/internal/app/vector-proxy-server.go @@ -4,6 +4,7 @@ import ( "context" "log/slog" "sync" + "time" "github.com/kloudlite/api/pkg/errors" @@ -36,7 +37,10 @@ func (v *vectorProxyServer) PushEvents(ctx context.Context, msg *proto_rpc.PushE logger.Debug("RECEIVED push-events message") - per, err := v.realVectorClient.PushEvents(ctx, msg) + nctx, cf := context.WithTimeout(ctx, 3*time.Second) + defer cf() + + per, err := v.realVectorClient.PushEvents(nctx, msg) if err != nil { logger.Error("FAILED to dispatch push-events message, got", "err", err) return nil, errors.NewE(err) diff --git a/apps/message-office/internal/domain/domain.go b/apps/message-office/internal/domain/domain.go index abc9544f4..4099220ed 100644 --- a/apps/message-office/internal/domain/domain.go +++ b/apps/message-office/internal/domain/domain.go @@ -8,6 +8,7 @@ import ( "go.uber.org/fx" platform_edge "github.com/kloudlite/api/apps/message-office/internal/domain/platform-edge" + "github.com/kloudlite/api/apps/message-office/internal/entities" "github.com/kloudlite/api/apps/message-office/internal/env" fn "github.com/kloudlite/api/pkg/functions" "github.com/kloudlite/api/pkg/repos" @@ -131,15 +132,21 @@ func (d *domain) GenClusterToken(ctx context.Context, accountName, clusterName s var Module = fx.Module( "domain", fx.Provide(func( + ev *env.Env, moRepo repos.DbRepo[*MessageOfficeToken], + edgeClustersRepo repos.DbRepo[*entities.PlatformEdgeCluster], + allocatedClustersRepo repos.DbRepo[*entities.ClusterAllocation], // accessTokenRepo repos.DbRepo[*AccessToken], logger *slog.Logger, ) Domain { return &domain{ moRepo: moRepo, - // accessTokenRepo: accessTokenRepo, - logger: logger, - PlatformEdgeDomain: PlatformEdgeDomain{Repo: &platform_edge.Repo{}}, + env: ev, + logger: logger, + PlatformEdgeDomain: PlatformEdgeDomain{Repo: &platform_edge.Repo{ + EdgeClusters: edgeClustersRepo, + AllocatedClusters: allocatedClustersRepo, + }}, } }), ) diff --git a/apps/message-office/internal/domain/platform-edge/repo.go b/apps/message-office/internal/domain/platform-edge/repo.go index 8321c754f..1e4f9992b 100644 --- a/apps/message-office/internal/domain/platform-edge/repo.go +++ b/apps/message-office/internal/domain/platform-edge/repo.go @@ -12,8 +12,8 @@ import ( ) type Repo struct { - edge_clusters repos.DbRepo[*entities.PlatformEdgeCluster] - allocated_clusters repos.DbRepo[*entities.ClusterAllocation] + EdgeClusters repos.DbRepo[*entities.PlatformEdgeCluster] + AllocatedClusters repos.DbRepo[*entities.ClusterAllocation] } func (r *Repo) ListPlatformEdgeClusters(ctx context.Context, region *string) ([]*entities.PlatformEdgeCluster, error) { @@ -23,11 +23,11 @@ func (r *Repo) ListPlatformEdgeClusters(ctx context.Context, region *string) ([] fc.PlatformEdgeClusterRegion: region, } } - return r.edge_clusters.Find(ctx, q) + return r.EdgeClusters.Find(ctx, q) } func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, account string) (*entities.PlatformEdgeCluster, error) { - m, err := r.allocated_clusters.GroupByAndCount(ctx, repos.Filter{fc.ClusterAllocationClusterRegion: region}, fc.ClusterAllocationClusterName, repos.GroupByAndCountOptions{ + m, err := r.AllocatedClusters.GroupByAndCount(ctx, repos.Filter{fc.ClusterAllocationClusterRegion: region}, fc.ClusterAllocationClusterName, repos.GroupByAndCountOptions{ Limit: 1, Sort: repos.SortDirectionAsc, }) @@ -44,7 +44,7 @@ func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, a switch len(m) { case 0: { - x, err := r.edge_clusters.FindOne(ctx, repos.Filter{fc.PlatformEdgeClusterRegion: region}) + x, err := r.EdgeClusters.FindOne(ctx, repos.Filter{fc.PlatformEdgeClusterRegion: region}) if err != nil { return nil, err } @@ -54,7 +54,7 @@ func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, a clusterName = x.Name - if _, err := r.allocated_clusters.Create(ctx, &entities.ClusterAllocation{ + if _, err := r.AllocatedClusters.Create(ctx, &entities.ClusterAllocation{ To: account, Cluster: entities.ClusterAllocationCluster{ Name: clusterName, @@ -74,7 +74,7 @@ func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, a } } - pec, err := r.edge_clusters.FindOne(ctx, repos.Filter{ + pec, err := r.EdgeClusters.FindOne(ctx, repos.Filter{ fc.PlatformEdgeClusterName: clusterName, fc.PlatformEdgeClusterRegion: region, }) @@ -90,7 +90,7 @@ func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, a } func (r *Repo) GetPlatformEdgeCluster(ctx context.Context, clusterName string) (*entities.PlatformEdgeCluster, error) { - pec, err := r.edge_clusters.FindOne(ctx, repos.Filter{ + pec, err := r.EdgeClusters.FindOne(ctx, repos.Filter{ fc.PlatformEdgeClusterName: clusterName, }) if err != nil { @@ -105,7 +105,7 @@ func (r *Repo) GetPlatformEdgeCluster(ctx context.Context, clusterName string) ( } func (r *Repo) GetAllocatedPlatformEdgeCluster(ctx context.Context, account string) (*entities.ClusterAllocation, error) { - rec, err := r.allocated_clusters.FindOne(ctx, repos.Filter{ + rec, err := r.AllocatedClusters.FindOne(ctx, repos.Filter{ fc.ClusterAllocationTo: account, }) if err != nil { diff --git a/apps/message-office/main.go b/apps/message-office/main.go index cbc4614d9..db13cba37 100644 --- a/apps/message-office/main.go +++ b/apps/message-office/main.go @@ -3,7 +3,6 @@ package main import ( "context" "flag" - "log/slog" "os" "time" @@ -26,10 +25,10 @@ func main() { flag.Parse() - logger, err := logging.New(&logging.Options{Name: "message-office", ShowDebugLog: isDev, HideCallerTrace: false}) - if err != nil { - panic(err) - } + start := time.Now() + common.PrintBuildInfo() + + logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug, SetAsDefaultLogger: true}) app := fx.New( fx.NopLogger, @@ -39,18 +38,12 @@ func main() { }), fx.Provide( - func() logging.Logger { - return logger + func() (logging.Logger, error) { + return logging.New(&logging.Options{Name: "message-office", ShowDebugLog: isDev, HideCallerTrace: false}) }, ), - fx.Provide(func() *slog.Logger { - return logging.NewSlogLogger(logging.SlogOptions{ - ShowCaller: true, - ShowDebugLogs: debug, - SetAsDefaultLogger: true, - }) - }), + fx.Supply(logger), fx.Provide(func() (*rest.Config, error) { if isDev { @@ -73,11 +66,10 @@ func main() { defer cancelFn() if err := app.Start(ctx); err != nil { - logger.Errorf(err, "message office startup errors") - logger.Infof("EXITING as errors encountered during startup") + logger.Error("failed to start message-office, got", "err", err) os.Exit(1) } - common.PrintReadyBanner() + common.PrintReadyBanner2(time.Since(start)) <-app.Done() } From 0f0ae41159de37e8c799a4a4e2666f2f3ce0d8ba Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Thu, 5 Sep 2024 17:57:12 +0530 Subject: [PATCH 05/17] feat(console): adds kloudlite edge clusters support for environments --- apps/console/Taskfile.yml | 33 ++++++++---- apps/console/internal/domain/domain.go | 54 +++++++++++++++---- .../field-constants/generated_constants.go | 15 ++++++ apps/console/main.go | 29 +++++----- 4 files changed, 98 insertions(+), 33 deletions(-) diff --git a/apps/console/Taskfile.yml b/apps/console/Taskfile.yml index c02a4b2e6..f78a75406 100644 --- a/apps/console/Taskfile.yml +++ b/apps/console/Taskfile.yml @@ -47,21 +47,15 @@ tasks: popd - rm -rf ./internal/app/_struct-to-graphql - run: - dotenv: - - .secrets/env - env: - CGO_ENABLED: 0 - cmds: - - go build -o bin/console ./main.go - - ./bin/console --dev - # - go run . --dev - gen:constants: cmds: - go generate ./internal/entities/field-constants/gen.go build: + vars: + platform_GOARCH: + sh: go env GOARCH + GOARCH: "{{ .GOARCH | default .platform_GOARCH }}" cmds: - task: gen:constants - task: go:build @@ -69,6 +63,25 @@ tasks: out: "{{.binary}}-{{.GOARCH}}" GOARCH: "{{.GOARCH}}" + run: + dotenv: + - .secrets/env + vars: + binary: '{{.binary | default "false"}}' + env: + CGO_ENABLED: 0 + silent: false + cmds: + - |+ + if [ "{{.binary}}" = "true" ]; then + task build + ./bin/console-$(go env GOARCH) --debug + else + echo "running go run" + go run ./main.go --dev + fi + + container:build-and-push: requires: vars: diff --git a/apps/console/internal/domain/domain.go b/apps/console/internal/domain/domain.go index 42a139535..d2a088a74 100644 --- a/apps/console/internal/domain/domain.go +++ b/apps/console/internal/domain/domain.go @@ -6,6 +6,7 @@ import ( "fmt" "strconv" + "github.com/kloudlite/api/pkg/grpc" "github.com/kloudlite/api/pkg/kv" "github.com/kloudlite/api/pkg/logging" @@ -171,7 +172,12 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj allocatedEdge, err := d.platformEdgeClient.GetAllocatedPlatformEdgeCluster(ctx, &platform_edge.GetAllocatedPlatformEdgeClusterIn{AccountName: ctx.GetAccountName()}) if err != nil { - if !errors.Is(err, mo_errors.ErrEdgeClusterNotAllocated) { + gErr := grpc.ParseErr(err) + if gErr == nil { + return errors.NewEf(err, "failed to get allocated edge cluster") + } + + if gErr.GetMessage() != mo_errors.ErrEdgeClusterNotAllocated.Error() { return errors.NewEf(err, "failed to get allocated edge cluster") } @@ -289,6 +295,11 @@ func applyK8sResource(ctx K8sContext, args ApplyK8sResourceArgs) error { } func (d *domain) restartK8sResource(ctx K8sContext, projectName string, namespace string, labels map[string]string) error { + var dispatchAddr struct { + AccountName string + ClusterName string + } + clusterName, err := d.getClusterAttachedToEnvironment(ctx, projectName) if err != nil { return errors.NewE(err) @@ -298,6 +309,25 @@ func (d *domain) restartK8sResource(ctx K8sContext, projectName string, namespac return nil } + switch *clusterName { + case "__kloudlite_enabled_cluster": + { + allocatedEdge, err := d.platformEdgeClient.GetAllocatedPlatformEdgeCluster(ctx, &platform_edge.GetAllocatedPlatformEdgeClusterIn{AccountName: ctx.GetAccountName()}) + if err != nil { + return errors.NewEf(err, "failed to get allocated edge cluster") + } + + dispatchAddr.AccountName = allocatedEdge.OwnedByAccount + dispatchAddr.ClusterName = allocatedEdge.ClusterName + } + default: + { + + dispatchAddr.AccountName = ctx.GetAccountName() + dispatchAddr.ClusterName = *clusterName + } + } + obj := unstructured.Unstructured{ Object: map[string]any{ "metadata": map[string]any{ @@ -317,7 +347,7 @@ func (d *domain) restartK8sResource(ctx K8sContext, projectName string, namespac return errors.NewE(err) } - subject := common.SendToAgentSubjectName(ctx.GetAccountName(), *clusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) + subject := common.SendToAgentSubjectName(dispatchAddr.AccountName, dispatchAddr.ClusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()) err = d.producer.Produce(ctx, msgTypes.ProduceMsg{ Subject: subject, @@ -355,6 +385,11 @@ func (d *domain) deleteK8sResourceOfCluster(ctx K8sContext, clusterName string, } func (d *domain) deleteK8sResource(ctx K8sContext, environmentName string, obj client.Object) error { + var dispatchAddr struct { + AccountName string + ClusterName string + } + clusterName, err := d.getClusterAttachedToEnvironment(ctx, environmentName) if err != nil { return ErrNoClusterAttached @@ -365,19 +400,16 @@ func (d *domain) deleteK8sResource(ctx K8sContext, environmentName string, obj c return ErrNoClusterAttached } - var dispatchAddr struct { - AccountName string - ClusterName string - } - switch *clusterName { case "__kloudlite_enabled_cluster": { - // dispatchAddr.AccountName = "kloudlite-edge-platform" - // dispatchAddr.ClusterName = "kl-edge-1" + allocatedEdge, err := d.platformEdgeClient.GetAllocatedPlatformEdgeCluster(ctx, &platform_edge.GetAllocatedPlatformEdgeClusterIn{AccountName: ctx.GetAccountName()}) + if err != nil { + return errors.NewEf(err, "failed to get allocated edge cluster") + } - dispatchAddr.AccountName = "nxt-multi-tenancy" - dispatchAddr.ClusterName = "sample" + dispatchAddr.AccountName = allocatedEdge.OwnedByAccount + dispatchAddr.ClusterName = allocatedEdge.ClusterName } default: { diff --git a/apps/console/internal/entities/field-constants/generated_constants.go b/apps/console/internal/entities/field-constants/generated_constants.go index 5cec8a8d9..b31327d13 100644 --- a/apps/console/internal/entities/field-constants/generated_constants.go +++ b/apps/console/internal/entities/field-constants/generated_constants.go @@ -149,6 +149,15 @@ const ( ImportedManagedResourceSecretRefNamespace = "secretRef.namespace" ) +// constant vars generated for struct KLoudliteEdgeCluster +const ( + KLoudliteEdgeClusterComments = "comments" + KLoudliteEdgeClusterMaxNumAccounts = "max_num_accounts" + KLoudliteEdgeClusterName = "name" + KLoudliteEdgeClusterNumAccounts = "num_accounts" + KLoudliteEdgeClusterRegion = "region" +) + // constant vars generated for struct ManagedResource const ( ManagedResourceEnabled = "enabled" @@ -207,6 +216,12 @@ const ( RegistryImageMeta = "meta" ) +// constant vars generated for struct RegistryImageURL +const ( + RegistryImageURLScriptUrl = "scriptUrl" + RegistryImageURLUrl = "url" +) + // constant vars generated for struct ResourceMapping const ( ResourceMappingBaseEntity = "BaseEntity" diff --git a/apps/console/main.go b/apps/console/main.go index d9af441ee..66a5fdb6b 100644 --- a/apps/console/main.go +++ b/apps/console/main.go @@ -25,22 +25,28 @@ func main() { var debug bool flag.BoolVar(&debug, "debug", false, "--debug") + flag.Parse() - logger, err := logging.New(&logging.Options{Name: "console", ShowDebugLog: debug}) - if err != nil { - panic(err) + if isDev { + debug = true } + common.PrintBuildInfo() + + logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug, SetAsDefaultLogger: true}) + + start := time.Now() + app := fx.New( + fx.StartTimeout(5*time.Second), fx.NopLogger, - - fx.Provide(func() logging.Logger { - return logger + fx.Provide(func() (logging.Logger, error) { + return logging.New(&logging.Options{Name: "console", ShowDebugLog: debug}) }), fx.Provide(func() *slog.Logger { - return logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug, SetAsDefaultLogger: true}) + return logger }), fx.Provide(func() (*env.Env, error) { @@ -65,18 +71,17 @@ func main() { ctx, cancelFunc := func() (context.Context, context.CancelFunc) { if isDev { - return context.WithTimeout(context.TODO(), 20*time.Second) + return context.WithTimeout(context.TODO(), 5*time.Second) } - return context.WithTimeout(context.TODO(), 5*time.Second) + return context.WithTimeout(context.TODO(), 10*time.Second) }() defer cancelFunc() if err := app.Start(ctx); err != nil { - logger.Errorf(err, "console startup errors") - logger.Infof("EXITING as errors encountered during startup") + logger.Error("while starting console, got", "err", err) os.Exit(1) } - common.PrintReadyBanner() + common.PrintReadyBanner2(time.Since(start)) <-app.Done() } From fffd46bdbc59071f59d7a9b85c9ec50e03b63147 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Fri, 13 Sep 2024 17:21:53 +0530 Subject: [PATCH 06/17] chore: `log/slog` logging for grpc and http servers --- pkg/grpc/logger.go | 22 ++++++++++++++++++++++ pkg/grpc/server.go | 14 +++----------- pkg/http-server/http-server.go | 15 +++++++++------ pkg/http-server/logger.go | 4 ++-- 4 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 pkg/grpc/logger.go diff --git a/pkg/grpc/logger.go b/pkg/grpc/logger.go new file mode 100644 index 000000000..7eee2faa4 --- /dev/null +++ b/pkg/grpc/logger.go @@ -0,0 +1,22 @@ +package grpc + +import ( + "fmt" + "log/slog" + "time" +) + +type logger struct { + *slog.Logger + comment string + t time.Time +} + +func NewRequestLogger(logr *slog.Logger, comment string) *logger { + logr.Debug("➡️ " + comment) + return &logger{Logger: logr, comment: comment, t: time.Now()} +} + +func (l *logger) End() { + l.Info("↩️ "+l.comment, "took", fmt.Sprintf("%.2fs", time.Since(l.t).Seconds())) +} diff --git a/pkg/grpc/server.go b/pkg/grpc/server.go index f8918e7e5..97c190914 100644 --- a/pkg/grpc/server.go +++ b/pkg/grpc/server.go @@ -33,11 +33,7 @@ func (g *grpcServer) Listen(addr string) error { if err != nil { return errors.NewEf(err, "could not listen to net/tcp server") } - if g.slogger != nil { - g.slogger.Info("grpc server listening", "at", addr) - } else { - g.logger.Infof("listening on %s", addr) - } + g.slogger.Info("grpc server listening", "at", addr) return g.Serve(listen) } @@ -46,12 +42,8 @@ func (g *grpcServer) Stop() { } func NewGrpcServer(opts ServerOpts) (Server, error) { - if opts.Logger == nil { - lgr, err := logging.New(&logging.Options{Name: "grpc-server", Dev: false}) - if err != nil { - return nil, errors.NewE(err) - } - opts.Logger = lgr + if opts.Slogger == nil { + opts.Slogger = slog.Default() } server := grpc.NewServer( diff --git a/pkg/http-server/http-server.go b/pkg/http-server/http-server.go index 5db89e9ed..b8715c882 100644 --- a/pkg/http-server/http-server.go +++ b/pkg/http-server/http-server.go @@ -3,6 +3,7 @@ package httpServer import ( "context" "fmt" + "log/slog" "net/http" "strings" "time" @@ -32,7 +33,7 @@ type Server interface { } type server struct { - Logger logging.Logger + logger *slog.Logger *fiber.App isDev bool } @@ -62,14 +63,16 @@ func (s *server) Listen(addr string) error { case status := <-errChannel: return errors.Newf("could not start server because %v", status.Error()) case <-ctx.Done(): - s.Logger.Infof("Http Server started @ (addr: %q)", addr) + s.logger.Info("HTTP server listening", "at", addr) } return nil } type ServerArgs struct { - IsDev bool + IsDev bool + // Logger is deprecated, now use Slogger Logger logging.Logger + Slogger *slog.Logger CorsAllowOrigins *string IAMGrpcAddr string `env:"IAM_GRPC_ADDR" required:"true"` } @@ -115,11 +118,11 @@ func NewServer(args ServerArgs) Server { ) } - if args.Logger == nil { - args.Logger = logging.EmptyLogger + if args.Slogger == nil { + args.Slogger = slog.Default() } - return &server{App: app, Logger: args.Logger, isDev: args.IsDev} + return &server{App: app, logger: args.Slogger, isDev: args.IsDev} } func (s *server) SetupGraphqlServer(es graphql.ExecutableSchema, middlewares ...fiber.Handler) { diff --git a/pkg/http-server/logger.go b/pkg/http-server/logger.go index e4cd31ec9..10732f4d3 100644 --- a/pkg/http-server/logger.go +++ b/pkg/http-server/logger.go @@ -27,9 +27,9 @@ func NewLoggingMiddleware(logger logging.Logger) HttpMiddleware { lrw := NewLoggingResponseWriter(w) timestart := time.Now() - logger.Infof("👉 %s %s?%s", r.Method, r.URL.Path, r.URL.Query().Encode()) + logger.Infof("➡️ %s %s?%s", r.Method, r.URL.Path, r.URL.Query().Encode()) defer func() { - logger.Infof("👈 %d %s %s?%s took %.2fs", lrw.statusCode, r.Method, r.URL.Path, r.URL.Query().Encode(), time.Since(timestart).Seconds()) + logger.Infof("↩️ %d %s %s?%s took %.2fs", lrw.statusCode, r.Method, r.URL.Path, r.URL.Query().Encode(), time.Since(timestart).Seconds()) }() next(w, r) From 4b21e99c500ad34a55c1ca27fbcc084bf97b9104 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Fri, 13 Sep 2024 17:25:00 +0530 Subject: [PATCH 07/17] chore(apps/webhook): startup message updates --- apps/webhook/main.go | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/webhook/main.go b/apps/webhook/main.go index d18e0842b..514962c67 100644 --- a/apps/webhook/main.go +++ b/apps/webhook/main.go @@ -1,11 +1,15 @@ package main import ( + "context" "flag" "log/slog" + "os" + "time" "github.com/kloudlite/api/apps/webhook/internal/env" "github.com/kloudlite/api/apps/webhook/internal/framework" + "github.com/kloudlite/api/common" "github.com/kloudlite/api/pkg/config" fn "github.com/kloudlite/api/pkg/functions" "github.com/kloudlite/api/pkg/logging" @@ -17,7 +21,13 @@ func main() { flag.BoolVar(&isDev, "dev", false, "--dev") flag.Parse() - fx.New( + start := time.Now() + common.PrintBuildInfo() + + logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: isDev, SetAsDefaultLogger: true}) + + app := fx.New( + fx.NopLogger, fx.Provide( func() (logging.Logger, error) { return logging.New(&logging.Options{Name: "webhooks", Dev: isDev}) @@ -35,5 +45,21 @@ func main() { fn.FxErrorHandler(), config.EnvFx[env.Env](), framework.Module, - ).Run() + ) + + ctx, cancel := func() (context.Context, context.CancelFunc) { + if isDev { + return context.WithTimeout(context.TODO(), 5*time.Second) + } + return context.WithTimeout(context.Background(), 2*time.Second) + }() + defer cancel() + + if err := app.Start(ctx); err != nil { + logger.Error("failed to start webhooks-api, got", slog.String("err", err.Error())) + os.Exit(1) + } + + common.PrintReadyBanner2(time.Since(start)) + <-app.Done() } From c1534e4b2451a0db472069f76d59f0b058b13b4d Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Sat, 14 Sep 2024 02:26:23 +0530 Subject: [PATCH 08/17] feat(message-office): platform edge clusters support, and grpc protobufs cleanup --- apps/message-office/Taskfile.yml | 2 +- .../internal/app/grpc-server.go | 3 +- .../internal/app/internal-grpc-server.go | 2 + .../internal/domain/platform-edge/repo.go | 3 +- .../domain/platform-edge/repo_test.go | 4 +- .../internal/entities/allocation.go | 48 +---------- .../field-constants/generated_constants.go | 16 +++- .../entities/platform-edge-cluster.go | 11 +-- .../protobufs/platform-edge.proto | 2 + .../platform-edge/platform-edge.pb.go | 83 ++++++++++++------- 10 files changed, 85 insertions(+), 89 deletions(-) diff --git a/apps/message-office/Taskfile.yml b/apps/message-office/Taskfile.yml index 79b4419f1..f74a81e18 100644 --- a/apps/message-office/Taskfile.yml +++ b/apps/message-office/Taskfile.yml @@ -37,7 +37,7 @@ tasks: cmds: - go generate ./internal/entities/field-constants/gen.go - grpc:build: + protobufs: dir: ./protobufs/ cmds: - protoc --go_out=. --go-grpc_out=. --go_opt=paths=import --go-grpc_opt=paths=import ./*.proto diff --git a/apps/message-office/internal/app/grpc-server.go b/apps/message-office/internal/app/grpc-server.go index b4925e6a3..6975ebd09 100644 --- a/apps/message-office/internal/app/grpc-server.go +++ b/apps/message-office/internal/app/grpc-server.go @@ -319,7 +319,7 @@ func processError(ctx context.Context, args ProcessErrorArgs) (err error) { // GetAccessToken implements messages.MessageDispatchServiceServer func (g *grpcServer) GetAccessToken(ctx context.Context, msg *messages.GetAccessTokenIn) (*messages.GetAccessTokenOut, error) { - g.logger.Debug("request received for cluster-token exchange") + g.logger.Debug("request received for cluster-token exchange", "cluster-token", msg.ClusterToken) ct, err := g.domain.FindClusterToken(ctx, msg.ClusterToken) if err != nil { @@ -363,6 +363,7 @@ func (g *grpcServer) SendActions(request *messages.Empty, server messages.Messag logger.Info("READY to transmit messages to agent") + // FIXME: online/offline status should be stored somewhere else other than the resource itself if _, err := g.infraClient.MarkClusterOnlineAt(server.Context(), &infra.MarkClusterOnlineAtIn{ AccountName: accountName, ClusterName: clusterName, diff --git a/apps/message-office/internal/app/internal-grpc-server.go b/apps/message-office/internal/app/internal-grpc-server.go index 59eeb4ded..4e4427c6d 100644 --- a/apps/message-office/internal/app/internal-grpc-server.go +++ b/apps/message-office/internal/app/internal-grpc-server.go @@ -50,6 +50,7 @@ func (s *internalServer) AllocatePlatformEdgeCluster(ctx context.Context, in *pl return &platform_edge.AllocatePlatformEdgeClusterOut{ ClusterName: pec.Name, OwnedByAccount: pec.OwnedByAccount, + PublicDnsHost: pec.PublicDNSHostname, }, nil } @@ -66,6 +67,7 @@ func (s *internalServer) GetAllocatedPlatformEdgeCluster(ctx context.Context, in return &platform_edge.AllocatePlatformEdgeClusterOut{ ClusterName: allocated.Cluster.Name, OwnedByAccount: allocated.Cluster.OwnedByAccount, + PublicDnsHost: allocated.Cluster.PublicDNSHost, }, nil } diff --git a/apps/message-office/internal/domain/platform-edge/repo.go b/apps/message-office/internal/domain/platform-edge/repo.go index 1e4f9992b..00dcda406 100644 --- a/apps/message-office/internal/domain/platform-edge/repo.go +++ b/apps/message-office/internal/domain/platform-edge/repo.go @@ -56,10 +56,11 @@ func (r *Repo) AllocatePlatformEdgeCluster(ctx context.Context, region string, a if _, err := r.AllocatedClusters.Create(ctx, &entities.ClusterAllocation{ To: account, - Cluster: entities.ClusterAllocationCluster{ + Cluster: entities.ClusterAllocationClusterRef{ Name: clusterName, Region: region, OwnedByAccount: x.OwnedByAccount, + PublicDNSHost: x.PublicDNSHostname, }, }); err != nil { return nil, err diff --git a/apps/message-office/internal/domain/platform-edge/repo_test.go b/apps/message-office/internal/domain/platform-edge/repo_test.go index d9820f493..a4c4ef4f7 100644 --- a/apps/message-office/internal/domain/platform-edge/repo_test.go +++ b/apps/message-office/internal/domain/platform-edge/repo_test.go @@ -175,8 +175,8 @@ func TestRepo_AllocatePlatformEdgeCluster(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { r := &Repo{ - edge_clusters: tt.fields.edge_clusters(t), - allocated_clusters: tt.fields.allocated_clusters(t), + EdgeClusters: tt.fields.edge_clusters(t), + AllocatedClusters: tt.fields.allocated_clusters(t), } got, err := r.AllocatePlatformEdgeCluster(tt.args.ctx, tt.args.region, tt.args.account) if (err != nil) && !errors.Is(err, tt.wantErr) { diff --git a/apps/message-office/internal/entities/allocation.go b/apps/message-office/internal/entities/allocation.go index 64c2e9a49..8618abae4 100644 --- a/apps/message-office/internal/entities/allocation.go +++ b/apps/message-office/internal/entities/allocation.go @@ -5,16 +5,17 @@ import ( "github.com/kloudlite/api/pkg/repos" ) -type ClusterAllocationCluster struct { +type ClusterAllocationClusterRef struct { Name string `json:"name"` Region string `json:"region"` OwnedByAccount string `json:"owned_by_account"` + PublicDNSHost string `json:"public_dns_host"` } type ClusterAllocation struct { repos.BaseEntity `json:",inline"` - To string `json:"to"` - Cluster ClusterAllocationCluster `json:"cluster"` + To string `json:"to"` + Cluster ClusterAllocationClusterRef `json:"cluster"` } var ClusterAllocationIndexes = []repos.IndexField{ @@ -37,44 +38,3 @@ var ClusterAllocationIndexes = []repos.IndexField{ }, }, } - -/* -```javascript -records = [] -for (let i = 1000; i < 10000; i++) { - records.push({ - id: i, - to: `A-${i}`, - cluster_name: `cluster-${Math.ceil(Math.random() * 10)}` - }); -} -db.cluster_allocations.insertMany(records); - -// [ -// { id: "1", to: "A", cluster_name: "cluster-1" }, -// { id: "2", to: "B", cluster_name: "cluster-1" }, -// { id: "3", to: "C", cluster_name: "cluster-2" }, -// { id: "4", to: "D", cluster_name: "cluster-2" }, -// { id: "5", to: "E", cluster_name: "cluster-3" }, -// { id: "6", to: "F", cluster_name: "cluster-3" }, -// { id: "7", to: "G", cluster_name: "cluster-4" }, -// ] -// ); - -db.cluster_allocations.aggregate([ - { - $group: { - _id: "$cluster_name", // Replace with the field you want to group by - count: { $sum: 1 } // Count the number of occurrences - } - }, - { - $sort: { count: 1 } // Sort by count in descending order - }, - { - $limit: 1 // Limit the results to the top 10 - } -]) - -``` -*/ diff --git a/apps/message-office/internal/entities/field-constants/generated_constants.go b/apps/message-office/internal/entities/field-constants/generated_constants.go index 8749ba63c..08bab37e5 100644 --- a/apps/message-office/internal/entities/field-constants/generated_constants.go +++ b/apps/message-office/internal/entities/field-constants/generated_constants.go @@ -11,12 +11,20 @@ const ( ClusterAllocationTo = "to" ) +// constant vars generated for struct ClusterAllocationClusterRef +const ( + ClusterAllocationClusterRefName = "name" + ClusterAllocationClusterRefOwnedByAccount = "owned_by_account" + ClusterAllocationClusterRefRegion = "region" +) + // constant vars generated for struct PlatformEdgeCluster const ( - PlatformEdgeClusterCloudProvider = "cloud_provider" - PlatformEdgeClusterName = "name" - PlatformEdgeClusterOwnedByAccount = "owned_by_account" - PlatformEdgeClusterRegion = "region" + PlatformEdgeClusterCloudProvider = "cloud_provider" + PlatformEdgeClusterName = "name" + PlatformEdgeClusterOwnedByAccount = "owned_by_account" + PlatformEdgeClusterPublicDnsHostname = "public_dns_hostname" + PlatformEdgeClusterRegion = "region" ) // constant vars generated for struct diff --git a/apps/message-office/internal/entities/platform-edge-cluster.go b/apps/message-office/internal/entities/platform-edge-cluster.go index b1f77408a..071de023a 100644 --- a/apps/message-office/internal/entities/platform-edge-cluster.go +++ b/apps/message-office/internal/entities/platform-edge-cluster.go @@ -6,11 +6,12 @@ import ( ) type PlatformEdgeCluster struct { - repos.BaseEntity `json:",inline"` - OwnedByAccount string `json:"owned_by_account"` - Name string `json:"name"` - Region string `json:"region"` - CloudProvider string `json:"cloud_provider"` + repos.BaseEntity `json:",inline"` + OwnedByAccount string `json:"owned_by_account"` + Name string `json:"name"` + Region string `json:"region"` + CloudProvider string `json:"cloud_provider"` + PublicDNSHostname string `json:"public_dns_hostname"` } var PlatformEdgeClusterIndexes = []repos.IndexField{ diff --git a/apps/message-office/protobufs/platform-edge.proto b/apps/message-office/protobufs/platform-edge.proto index 6688634d4..5831fd6ec 100644 --- a/apps/message-office/protobufs/platform-edge.proto +++ b/apps/message-office/protobufs/platform-edge.proto @@ -29,8 +29,10 @@ message AllocatePlatformEdgeClusterIn { message AllocatePlatformEdgeClusterOut { string cluster_name = 1; string owned_by_account = 2; + string public_dns_host = 3; } message GetAllocatedPlatformEdgeClusterIn { string account_name = 1; + string cluster_name = 2; } diff --git a/apps/message-office/protobufs/platform-edge/platform-edge.pb.go b/apps/message-office/protobufs/platform-edge/platform-edge.pb.go index 9ea255aa9..257c18f65 100644 --- a/apps/message-office/protobufs/platform-edge/platform-edge.pb.go +++ b/apps/message-office/protobufs/platform-edge/platform-edge.pb.go @@ -231,6 +231,7 @@ type AllocatePlatformEdgeClusterOut struct { ClusterName string `protobuf:"bytes,1,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` OwnedByAccount string `protobuf:"bytes,2,opt,name=owned_by_account,json=ownedByAccount,proto3" json:"owned_by_account,omitempty"` + PublicDnsHost string `protobuf:"bytes,3,opt,name=public_dns_host,json=publicDnsHost,proto3" json:"public_dns_host,omitempty"` } func (x *AllocatePlatformEdgeClusterOut) Reset() { @@ -279,12 +280,20 @@ func (x *AllocatePlatformEdgeClusterOut) GetOwnedByAccount() string { return "" } +func (x *AllocatePlatformEdgeClusterOut) GetPublicDnsHost() string { + if x != nil { + return x.PublicDnsHost + } + return "" +} + type GetAllocatedPlatformEdgeClusterIn struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields AccountName string `protobuf:"bytes,1,opt,name=account_name,json=accountName,proto3" json:"account_name,omitempty"` + ClusterName string `protobuf:"bytes,2,opt,name=cluster_name,json=clusterName,proto3" json:"cluster_name,omitempty"` } func (x *GetAllocatedPlatformEdgeClusterIn) Reset() { @@ -326,6 +335,13 @@ func (x *GetAllocatedPlatformEdgeClusterIn) GetAccountName() string { return "" } +func (x *GetAllocatedPlatformEdgeClusterIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + var File_platform_edge_proto protoreflect.FileDescriptor var file_platform_edge_proto_rawDesc = []byte{ @@ -351,39 +367,44 @@ var file_platform_edge_proto_rawDesc = []byte{ 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x6d, 0x0a, 0x1e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x95, 0x01, 0x0a, 0x1e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x77, + 0x6e, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x42, 0x79, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, + 0x6e, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x6e, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x69, 0x0a, 0x21, + 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, + 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x32, 0xad, 0x02, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x74, + 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x12, 0x55, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x77, 0x6e, - 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x64, 0x42, 0x79, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x32, 0xad, 0x02, 0x0a, 0x0c, - 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x12, 0x55, 0x0a, 0x18, - 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x73, 0x49, 0x6e, 0x1a, 0x1c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, - 0x4f, 0x75, 0x74, 0x12, 0x5e, 0x0a, 0x1b, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, + 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x49, + 0x6e, 0x1a, 0x1c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x4f, 0x75, 0x74, 0x12, + 0x5e, 0x0a, 0x1b, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, + 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1e, + 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x1a, 0x1f, + 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x12, + 0x66, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x49, 0x6e, 0x1a, 0x1f, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4f, 0x75, 0x74, 0x12, 0x66, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, - 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x1a, 0x1f, 0x2e, 0x41, 0x6c, 0x6c, - 0x6f, 0x63, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, - 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x42, 0x11, 0x5a, 0x0f, 0x2e, - 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x72, 0x12, 0x22, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x1a, 0x1f, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x64, 0x67, 0x65, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x42, 0x11, 0x5a, 0x0f, 0x2e, 0x2f, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x64, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( From 524cac83c2f2bc09562d26f87e50743ed6e565d3 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Sat, 14 Sep 2024 02:29:53 +0530 Subject: [PATCH 09/17] feat(console): supoprts environment creation on kloudlite clusters --- apps/console/Taskfile.yml | 4 +- .../internal/app/adapters/account-svc.go | 3 - .../adapters/infra-service/infra-service.go | 39 ++ .../adapters/resource-dispatch/dispatch.go | 1 + apps/console/internal/app/app.go | 8 +- apps/console/internal/app/gqlgen.yml | 7 + .../internal/app/graph/generated/generated.go | 463 +++++++++++++++++- .../internal/app/graph/model/models_gen.go | 5 + .../internal/app/graph/schema.graphqls | 12 + .../internal/app/graph/schema.resolvers.go | 32 +- .../internal/app/process-resource-updates.go | 18 +- apps/console/internal/domain/api.go | 6 + apps/console/internal/domain/domain.go | 40 +- .../internal/domain/environments/domain.go | 42 ++ .../internal/domain/environments/errors.go | 1 + .../internal/domain/environments/repo.go | 211 ++++++++ .../internal/domain/environments/repo_test.go | 1 + .../domain/kloudlite-edge-cluster/domain.go | 9 - .../internal/domain/ports/iam-service.go | 20 + .../internal/domain/ports/infra-service.go | 20 + .../domain/ports/resource-dispatch.go | 15 + .../internal/domain/types/event-publisher.go | 18 + apps/console/internal/domain/types/types.go | 43 ++ apps/console/internal/entities/environment.go | 2 +- apps/console/main.go | 19 +- 25 files changed, 981 insertions(+), 58 deletions(-) create mode 100644 apps/console/internal/app/adapters/infra-service/infra-service.go create mode 100644 apps/console/internal/app/adapters/resource-dispatch/dispatch.go create mode 100644 apps/console/internal/domain/environments/domain.go create mode 100644 apps/console/internal/domain/environments/errors.go create mode 100644 apps/console/internal/domain/environments/repo.go create mode 100644 apps/console/internal/domain/environments/repo_test.go delete mode 100644 apps/console/internal/domain/kloudlite-edge-cluster/domain.go create mode 100644 apps/console/internal/domain/ports/iam-service.go create mode 100644 apps/console/internal/domain/ports/infra-service.go create mode 100644 apps/console/internal/domain/ports/resource-dispatch.go create mode 100644 apps/console/internal/domain/types/event-publisher.go create mode 100644 apps/console/internal/domain/types/types.go diff --git a/apps/console/Taskfile.yml b/apps/console/Taskfile.yml index f78a75406..ad69b2b8b 100644 --- a/apps/console/Taskfile.yml +++ b/apps/console/Taskfile.yml @@ -70,18 +70,16 @@ tasks: binary: '{{.binary | default "false"}}' env: CGO_ENABLED: 0 - silent: false + silent: true cmds: - |+ if [ "{{.binary}}" = "true" ]; then task build ./bin/console-$(go env GOARCH) --debug else - echo "running go run" go run ./main.go --dev fi - container:build-and-push: requires: vars: diff --git a/apps/console/internal/app/adapters/account-svc.go b/apps/console/internal/app/adapters/account-svc.go index d3d257738..40f016061 100644 --- a/apps/console/internal/app/adapters/account-svc.go +++ b/apps/console/internal/app/adapters/account-svc.go @@ -23,9 +23,6 @@ func (as *accountsSvc) GetAccountRegion(ctx context.Context, userId string, acco AccountName: accountName, }) if err != nil { - // if errors.Is(err, context.DeadlineExceeded) { - // return nil, domain.ErrGRPCCall{Err: err} - // } return "", errors.NewE(err) } diff --git a/apps/console/internal/app/adapters/infra-service/infra-service.go b/apps/console/internal/app/adapters/infra-service/infra-service.go new file mode 100644 index 000000000..b11212b81 --- /dev/null +++ b/apps/console/internal/app/adapters/infra-service/infra-service.go @@ -0,0 +1,39 @@ +package infra_service + +import ( + "context" + + "github.com/kloudlite/api/apps/console/internal/domain/ports" + "github.com/kloudlite/api/apps/infra/protobufs/infra" +) + +type InfraService struct { + infraClient infra.InfraClient +} + +// EnsureGlobalVPNConnection implements ports.InfraService. +func (s *InfraService) EnsureGlobalVPNConnection(ctx context.Context, args ports.EnsureGlobalVPNConnectionIn) error { + _, err := s.infraClient.EnsureGlobalVPNConnection(ctx, &infra.EnsureGlobalVPNConnectionIn{ + UserId: args.UserId, + UserName: args.UserName, + UserEmail: args.UserEmail, + AccountName: args.AccountName, + ClusterName: args.ClusterName, + GlobalVPNName: args.GlobalVPNName, + DispatchAddr_AccountName: args.DispatchAddrAccountName, + DispatchAddr_ClusterName: args.DispatchAddrClusterName, + }) + if err != nil { + return err + } + + return nil +} + +var _ ports.InfraService = (*InfraService)(nil) + +func NewInfraService(infraClient infra.InfraClient) ports.InfraService { + return &InfraService{ + infraClient: infraClient, + } +} diff --git a/apps/console/internal/app/adapters/resource-dispatch/dispatch.go b/apps/console/internal/app/adapters/resource-dispatch/dispatch.go new file mode 100644 index 000000000..fe44476b6 --- /dev/null +++ b/apps/console/internal/app/adapters/resource-dispatch/dispatch.go @@ -0,0 +1 @@ +package resource_dispatch diff --git a/apps/console/internal/app/app.go b/apps/console/internal/app/app.go index ebe01870d..e710bf5ec 100644 --- a/apps/console/internal/app/app.go +++ b/apps/console/internal/app/app.go @@ -15,15 +15,17 @@ import ( "go.uber.org/fx" "github.com/kloudlite/api/apps/console/internal/app/adapters" + infra_service "github.com/kloudlite/api/apps/console/internal/app/adapters/infra-service" "github.com/kloudlite/api/apps/console/internal/app/graph" "github.com/kloudlite/api/apps/console/internal/app/graph/generated" "github.com/kloudlite/api/apps/console/internal/domain" + "github.com/kloudlite/api/apps/console/internal/domain/ports" "github.com/kloudlite/api/apps/console/internal/entities" "github.com/kloudlite/api/apps/console/internal/env" + "github.com/kloudlite/api/apps/infra/protobufs/infra" platform_edge "github.com/kloudlite/api/apps/message-office/protobufs/platform-edge" "github.com/kloudlite/api/common" "github.com/kloudlite/api/constants" - "github.com/kloudlite/api/grpc-interfaces/infra" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" "github.com/kloudlite/api/pkg/grpc" httpServer "github.com/kloudlite/api/pkg/http-server" @@ -96,6 +98,10 @@ var Module = fx.Module("app", fx.Provide(adapters.NewAccountsSvc), + fx.Provide(func(cli infra.InfraClient) ports.InfraService { + return infra_service.NewInfraService(cli) + }), + fx.Invoke( func(server httpServer.Server, d domain.Domain, sessionRepo kv.Repo[*common.AuthSession], ev *env.Env) { gqlConfig := generated.Config{Resolvers: &graph.Resolver{Domain: d, EnvVars: ev}} diff --git a/apps/console/internal/app/gqlgen.yml b/apps/console/internal/app/gqlgen.yml index cec924e7b..2834111e8 100644 --- a/apps/console/internal/app/gqlgen.yml +++ b/apps/console/internal/app/gqlgen.yml @@ -78,6 +78,9 @@ models: Environment: &environment-model model: github.com/kloudlite/api/apps/console/internal/entities.Environment + fields: + onlineStatus: + resolver: true EnvironmentIn: *environment-model RegistryImage: ®istry-image-model @@ -117,6 +120,8 @@ models: resolver: true serviceHost: resolver: true + onlineStatus: + resolver: true model: github.com/kloudlite/api/apps/console/internal/entities.App AppIn: *app-model @@ -152,6 +157,8 @@ models: fields: managedResource: resolver: true + onlineStatus: + resolver: true ClusterManagedService: &custer-managed-service-model model: github.com/kloudlite/api/apps/console/internal/entities.ClusterManagedService diff --git a/apps/console/internal/app/graph/generated/generated.go b/apps/console/internal/app/graph/generated/generated.go index 792f6e81d..a69dec4ed 100644 --- a/apps/console/internal/app/graph/generated/generated.go +++ b/apps/console/internal/app/graph/generated/generated.go @@ -104,6 +104,7 @@ type ComplexityRoot struct { LastUpdatedBy func(childComplexity int) int MarkedForDeletion func(childComplexity int) int ObjectMeta func(childComplexity int) int + OnlineStatus func(childComplexity int) int RecordVersion func(childComplexity int) int ServiceHost func(childComplexity int) int Spec func(childComplexity int) int @@ -231,6 +232,7 @@ type ComplexityRoot struct { LastUpdatedBy func(childComplexity int) int MarkedForDeletion func(childComplexity int) int ObjectMeta func(childComplexity int) int + OnlineStatus func(childComplexity int) int RecordVersion func(childComplexity int) int Spec func(childComplexity int) int Status func(childComplexity int) int @@ -615,6 +617,7 @@ type ComplexityRoot struct { ManagedResourceRef func(childComplexity int) int MarkedForDeletion func(childComplexity int) int Name func(childComplexity int) int + OnlineStatus func(childComplexity int) int RecordVersion func(childComplexity int) int SecretRef func(childComplexity int) int SyncStatus func(childComplexity int) int @@ -775,6 +778,11 @@ type ComplexityRoot struct { InfraUpdateClusterManagedService func(childComplexity int, service entities.ClusterManagedService) int } + OnlineStatus struct { + LastOnlineAt func(childComplexity int) int + WillBeOfflineAt func(childComplexity int) int + } + PageInfo struct { EndCursor func(childComplexity int) int HasNextPage func(childComplexity int) int @@ -967,6 +975,7 @@ type AppResolver interface { UpdateTime(ctx context.Context, obj *entities.App) (string, error) Build(ctx context.Context, obj *entities.App) (*model.Build, error) ServiceHost(ctx context.Context, obj *entities.App) (*string, error) + OnlineStatus(ctx context.Context, obj *entities.App) (*model.OnlineStatus, error) } type ClusterManagedServiceResolver interface { CreationTime(ctx context.Context, obj *entities.ClusterManagedService) (string, error) @@ -992,6 +1001,7 @@ type EnvironmentResolver interface { Spec(ctx context.Context, obj *entities.Environment) (*model.GithubComKloudliteOperatorApisCrdsV1EnvironmentSpec, error) UpdateTime(ctx context.Context, obj *entities.Environment) (string, error) + OnlineStatus(ctx context.Context, obj *entities.Environment) (*model.OnlineStatus, error) } type ExternalAppResolver interface { CreationTime(ctx context.Context, obj *entities.ExternalApp) (string, error) @@ -1034,6 +1044,7 @@ type ImportedManagedResourceResolver interface { UpdateTime(ctx context.Context, obj *entities.ImportedManagedResource) (string, error) ManagedResource(ctx context.Context, obj *entities.ImportedManagedResource) (*entities.ManagedResource, error) + OnlineStatus(ctx context.Context, obj *entities.ImportedManagedResource) (*model.OnlineStatus, error) } type K8s__io___api___core___v1__SecretResolver interface { Data(ctx context.Context, obj *v11.Secret) (map[string]interface{}, error) @@ -1329,6 +1340,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.App.ObjectMeta(childComplexity), true + case "App.onlineStatus": + if e.complexity.App.OnlineStatus == nil { + break + } + + return e.complexity.App.OnlineStatus(childComplexity), true + case "App.recordVersion": if e.complexity.App.RecordVersion == nil { break @@ -1908,6 +1926,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Environment.ObjectMeta(childComplexity), true + case "Environment.onlineStatus": + if e.complexity.Environment.OnlineStatus == nil { + break + } + + return e.complexity.Environment.OnlineStatus(childComplexity), true + case "Environment.recordVersion": if e.complexity.Environment.RecordVersion == nil { break @@ -3546,6 +3571,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ImportedManagedResource.Name(childComplexity), true + case "ImportedManagedResource.onlineStatus": + if e.complexity.ImportedManagedResource.OnlineStatus == nil { + break + } + + return e.complexity.ImportedManagedResource.OnlineStatus(childComplexity), true + case "ImportedManagedResource.recordVersion": if e.complexity.ImportedManagedResource.RecordVersion == nil { break @@ -4512,6 +4544,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.InfraUpdateClusterManagedService(childComplexity, args["service"].(entities.ClusterManagedService)), true + case "OnlineStatus.lastOnlineAt": + if e.complexity.OnlineStatus.LastOnlineAt == nil { + break + } + + return e.complexity.OnlineStatus.LastOnlineAt(childComplexity), true + + case "OnlineStatus.willBeOfflineAt": + if e.complexity.OnlineStatus.WillBeOfflineAt == nil { + break + } + + return e.complexity.OnlineStatus.WillBeOfflineAt(childComplexity), true + case "PageInfo.endCursor": if e.complexity.PageInfo.EndCursor == nil { break @@ -5974,14 +6020,26 @@ type Build @key(fields: "id") { id: ID! @isLoggedInAndVerified @hasAccount } +type OnlineStatus { + lastOnlineAt: Date! + willBeOfflineAt: Date! +} + +extend type Environment { + onlineStatus: OnlineStatus +} + extend type App { build: Build serviceHost: String + onlineStatus: OnlineStatus } extend type ImportedManagedResource { managedResource: ManagedResource + onlineStatus: OnlineStatus } + `, BuiltIn: false}, {Name: "../struct-to-graphql/app.graphqls", Input: `type App @shareable { accountName: String! @@ -10247,6 +10305,53 @@ func (ec *executionContext) fieldContext_App_serviceHost(_ context.Context, fiel return fc, nil } +func (ec *executionContext) _App_onlineStatus(ctx context.Context, field graphql.CollectedField, obj *entities.App) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_App_onlineStatus(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.App().OnlineStatus(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.OnlineStatus) + fc.Result = res + return ec.marshalOOnlineStatus2ᚖgithubᚗcomᚋkloudliteᚋapiᚋappsᚋconsoleᚋinternalᚋappᚋgraphᚋmodelᚐOnlineStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_App_onlineStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "App", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "lastOnlineAt": + return ec.fieldContext_OnlineStatus_lastOnlineAt(ctx, field) + case "willBeOfflineAt": + return ec.fieldContext_OnlineStatus_willBeOfflineAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type OnlineStatus", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _AppEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *model.AppEdge) (ret graphql.Marshaler) { fc, err := ec.fieldContext_AppEdge_cursor(ctx, field) if err != nil { @@ -10370,6 +10475,8 @@ func (ec *executionContext) fieldContext_AppEdge_node(_ context.Context, field g return ec.fieldContext_App_build(ctx, field) case "serviceHost": return ec.fieldContext_App_serviceHost(ctx, field) + case "onlineStatus": + return ec.fieldContext_App_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type App", field.Name) }, @@ -14114,6 +14221,53 @@ func (ec *executionContext) fieldContext_Environment_updateTime(_ context.Contex return fc, nil } +func (ec *executionContext) _Environment_onlineStatus(ctx context.Context, field graphql.CollectedField, obj *entities.Environment) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Environment_onlineStatus(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Environment().OnlineStatus(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.OnlineStatus) + fc.Result = res + return ec.marshalOOnlineStatus2ᚖgithubᚗcomᚋkloudliteᚋapiᚋappsᚋconsoleᚋinternalᚋappᚋgraphᚋmodelᚐOnlineStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Environment_onlineStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Environment", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "lastOnlineAt": + return ec.fieldContext_OnlineStatus_lastOnlineAt(ctx, field) + case "willBeOfflineAt": + return ec.fieldContext_OnlineStatus_willBeOfflineAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type OnlineStatus", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _EnvironmentEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *model.EnvironmentEdge) (ret graphql.Marshaler) { fc, err := ec.fieldContext_EnvironmentEdge_cursor(ctx, field) if err != nil { @@ -14231,6 +14385,8 @@ func (ec *executionContext) fieldContext_EnvironmentEdge_node(_ context.Context, return ec.fieldContext_Environment_syncStatus(ctx, field) case "updateTime": return ec.fieldContext_Environment_updateTime(ctx, field) + case "onlineStatus": + return ec.fieldContext_Environment_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Environment", field.Name) }, @@ -24742,6 +24898,53 @@ func (ec *executionContext) fieldContext_ImportedManagedResource_managedResource return fc, nil } +func (ec *executionContext) _ImportedManagedResource_onlineStatus(ctx context.Context, field graphql.CollectedField, obj *entities.ImportedManagedResource) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_ImportedManagedResource_onlineStatus(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.ImportedManagedResource().OnlineStatus(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.OnlineStatus) + fc.Result = res + return ec.marshalOOnlineStatus2ᚖgithubᚗcomᚋkloudliteᚋapiᚋappsᚋconsoleᚋinternalᚋappᚋgraphᚋmodelᚐOnlineStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_ImportedManagedResource_onlineStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ImportedManagedResource", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "lastOnlineAt": + return ec.fieldContext_OnlineStatus_lastOnlineAt(ctx, field) + case "willBeOfflineAt": + return ec.fieldContext_OnlineStatus_willBeOfflineAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type OnlineStatus", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _ImportedManagedResourceEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *model.ImportedManagedResourceEdge) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ImportedManagedResourceEdge_cursor(ctx, field) if err != nil { @@ -24855,6 +25058,8 @@ func (ec *executionContext) fieldContext_ImportedManagedResourceEdge_node(_ cont return ec.fieldContext_ImportedManagedResource_updateTime(ctx, field) case "managedResource": return ec.fieldContext_ImportedManagedResource_managedResource(ctx, field) + case "onlineStatus": + return ec.fieldContext_ImportedManagedResource_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ImportedManagedResource", field.Name) }, @@ -28213,6 +28418,8 @@ func (ec *executionContext) fieldContext_Mutation_core_createEnvironment(ctx con return ec.fieldContext_Environment_syncStatus(ctx, field) case "updateTime": return ec.fieldContext_Environment_updateTime(ctx, field) + case "onlineStatus": + return ec.fieldContext_Environment_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Environment", field.Name) }, @@ -28327,6 +28534,8 @@ func (ec *executionContext) fieldContext_Mutation_core_updateEnvironment(ctx con return ec.fieldContext_Environment_syncStatus(ctx, field) case "updateTime": return ec.fieldContext_Environment_updateTime(ctx, field) + case "onlineStatus": + return ec.fieldContext_Environment_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Environment", field.Name) }, @@ -28522,6 +28731,8 @@ func (ec *executionContext) fieldContext_Mutation_core_cloneEnvironment(ctx cont return ec.fieldContext_Environment_syncStatus(ctx, field) case "updateTime": return ec.fieldContext_Environment_updateTime(ctx, field) + case "onlineStatus": + return ec.fieldContext_Environment_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Environment", field.Name) }, @@ -29032,6 +29243,8 @@ func (ec *executionContext) fieldContext_Mutation_core_createApp(ctx context.Con return ec.fieldContext_App_build(ctx, field) case "serviceHost": return ec.fieldContext_App_serviceHost(ctx, field) + case "onlineStatus": + return ec.fieldContext_App_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type App", field.Name) }, @@ -29152,6 +29365,8 @@ func (ec *executionContext) fieldContext_Mutation_core_updateApp(ctx context.Con return ec.fieldContext_App_build(ctx, field) case "serviceHost": return ec.fieldContext_App_serviceHost(ctx, field) + case "onlineStatus": + return ec.fieldContext_App_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type App", field.Name) }, @@ -31582,6 +31797,8 @@ func (ec *executionContext) fieldContext_Mutation_core_importManagedResource(ctx return ec.fieldContext_ImportedManagedResource_updateTime(ctx, field) case "managedResource": return ec.fieldContext_ImportedManagedResource_managedResource(ctx, field) + case "onlineStatus": + return ec.fieldContext_ImportedManagedResource_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type ImportedManagedResource", field.Name) }, @@ -31681,6 +31898,94 @@ func (ec *executionContext) fieldContext_Mutation_core_deleteImportedManagedReso return fc, nil } +func (ec *executionContext) _OnlineStatus_lastOnlineAt(ctx context.Context, field graphql.CollectedField, obj *model.OnlineStatus) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnlineStatus_lastOnlineAt(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.LastOnlineAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNDate2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnlineStatus_lastOnlineAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnlineStatus", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Date does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _OnlineStatus_willBeOfflineAt(ctx context.Context, field graphql.CollectedField, obj *model.OnlineStatus) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_OnlineStatus_willBeOfflineAt(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.WillBeOfflineAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNDate2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_OnlineStatus_willBeOfflineAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "OnlineStatus", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Date does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PageInfo_endCursor(ctx, field) if err != nil { @@ -32196,6 +32501,8 @@ func (ec *executionContext) fieldContext_Query_core_getEnvironment(ctx context.C return ec.fieldContext_Environment_syncStatus(ctx, field) case "updateTime": return ec.fieldContext_Environment_updateTime(ctx, field) + case "onlineStatus": + return ec.fieldContext_Environment_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Environment", field.Name) }, @@ -33035,6 +33342,8 @@ func (ec *executionContext) fieldContext_Query_core_getApp(ctx context.Context, return ec.fieldContext_App_build(ctx, field) case "serviceHost": return ec.fieldContext_App_serviceHost(ctx, field) + case "onlineStatus": + return ec.fieldContext_App_onlineStatus(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type App", field.Name) }, @@ -45354,6 +45663,39 @@ func (ec *executionContext) _App(ctx context.Context, sel ast.SelectionSet, obj continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "onlineStatus": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._App_onlineStatus(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -46520,6 +46862,39 @@ func (ec *executionContext) _Environment(ctx context.Context, sel ast.SelectionS continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "onlineStatus": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Environment_onlineStatus(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -49639,6 +50014,39 @@ func (ec *executionContext) _ImportedManagedResource(ctx context.Context, sel as continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "onlineStatus": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._ImportedManagedResource_onlineStatus(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -50938,6 +51346,50 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return out } +var onlineStatusImplementors = []string{"OnlineStatus"} + +func (ec *executionContext) _OnlineStatus(ctx context.Context, sel ast.SelectionSet, obj *model.OnlineStatus) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, onlineStatusImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("OnlineStatus") + case "lastOnlineAt": + out.Values[i] = ec._OnlineStatus_lastOnlineAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "willBeOfflineAt": + out.Values[i] = ec._OnlineStatus_willBeOfflineAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var pageInfoImplementors = []string{"PageInfo"} func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *model.PageInfo) graphql.Marshaler { @@ -54773,12 +55225,12 @@ func (ec *executionContext) marshalNManagedResourceKeyValueRef2ᚖgithubᚗcom return ec._ManagedResourceKeyValueRef(ctx, sel, v) } -func (ec *executionContext) unmarshalNMap2map(ctx context.Context, v interface{}) (map[string]interface{}, error) { +func (ec *executionContext) unmarshalNMap2map(ctx context.Context, v interface{}) (map[string]any, error) { res, err := graphql.UnmarshalMap(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNMap2map(ctx context.Context, sel ast.SelectionSet, v map[string]interface{}) graphql.Marshaler { +func (ec *executionContext) marshalNMap2map(ctx context.Context, sel ast.SelectionSet, v map[string]any) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -57305,6 +57757,13 @@ func (ec *executionContext) unmarshalOMetadataIn2ᚖk8sᚗioᚋapimachineryᚋpk return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalOOnlineStatus2ᚖgithubᚗcomᚋkloudliteᚋapiᚋappsᚋconsoleᚋinternalᚋappᚋgraphᚋmodelᚐOnlineStatus(ctx context.Context, sel ast.SelectionSet, v *model.OnlineStatus) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._OnlineStatus(ctx, sel, v) +} + func (ec *executionContext) marshalORegistryImage2ᚖgithubᚗcomᚋkloudliteᚋapiᚋappsᚋconsoleᚋinternalᚋentitiesᚐRegistryImage(ctx context.Context, sel ast.SelectionSet, v *entities.RegistryImage) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/apps/console/internal/app/graph/model/models_gen.go b/apps/console/internal/app/graph/model/models_gen.go index 12482df01..cfd28412a 100644 --- a/apps/console/internal/app/graph/model/models_gen.go +++ b/apps/console/internal/app/graph/model/models_gen.go @@ -739,6 +739,11 @@ type ManagedResourcePaginatedRecords struct { type Mutation struct { } +type OnlineStatus struct { + LastOnlineAt string `json:"lastOnlineAt"` + WillBeOfflineAt string `json:"willBeOfflineAt"` +} + type PageInfo struct { EndCursor *string `json:"endCursor,omitempty"` HasNextPage *bool `json:"hasNextPage,omitempty"` diff --git a/apps/console/internal/app/graph/schema.graphqls b/apps/console/internal/app/graph/schema.graphqls index 2cc5fa3b0..2c5ad8eed 100644 --- a/apps/console/internal/app/graph/schema.graphqls +++ b/apps/console/internal/app/graph/schema.graphqls @@ -208,11 +208,23 @@ type Build @key(fields: "id") { id: ID! @isLoggedInAndVerified @hasAccount } +type OnlineStatus { + lastOnlineAt: Date! + willBeOfflineAt: Date! +} + +extend type Environment { + onlineStatus: OnlineStatus +} + extend type App { build: Build serviceHost: String + onlineStatus: OnlineStatus } extend type ImportedManagedResource { managedResource: ManagedResource + onlineStatus: OnlineStatus } + diff --git a/apps/console/internal/app/graph/schema.resolvers.go b/apps/console/internal/app/graph/schema.resolvers.go index 1e3c9e648..ef4cf7bb6 100644 --- a/apps/console/internal/app/graph/schema.resolvers.go +++ b/apps/console/internal/app/graph/schema.resolvers.go @@ -7,6 +7,8 @@ package graph import ( "context" "fmt" + "time" + "github.com/kloudlite/api/pkg/errors" "github.com/kloudlite/api/apps/console/internal/app/graph/generated" @@ -35,6 +37,22 @@ func (r *appResolver) ServiceHost(ctx context.Context, obj *entities.App) (*stri return fn.New(fmt.Sprintf("%s.%s.%s.%s", obj.Name, obj.EnvironmentName, obj.AccountName, r.EnvVars.KloudliteDNSSuffix)), nil } +// OnlineStatus is the resolver for the onlineStatus field. +func (r *appResolver) OnlineStatus(ctx context.Context, obj *entities.App) (*model.OnlineStatus, error) { + return &model.OnlineStatus{ + LastOnlineAt: time.Now().Format(time.RFC3339), + WillBeOfflineAt: time.Now().Add(2 * time.Minute).Format(time.RFC3339), + }, nil +} + +// OnlineStatus is the resolver for the onlineStatus field. +func (r *environmentResolver) OnlineStatus(ctx context.Context, obj *entities.Environment) (*model.OnlineStatus, error) { + return &model.OnlineStatus{ + LastOnlineAt: time.Now().Format(time.RFC3339), + WillBeOfflineAt: time.Now().Add(2 * time.Minute).Format(time.RFC3339), + }, nil +} + // ManagedResource is the resolver for the ManagedResource field. func (r *importedManagedResourceResolver) ManagedResource(ctx context.Context, obj *entities.ImportedManagedResource) (*entities.ManagedResource, error) { cc, err := toConsoleContext(ctx) @@ -44,6 +62,14 @@ func (r *importedManagedResourceResolver) ManagedResource(ctx context.Context, o return r.Domain.GetManagedResourceByID(cc, obj.ManagedResourceRef.ID) } +// OnlineStatus is the resolver for the onlineStatus field. +func (r *importedManagedResourceResolver) OnlineStatus(ctx context.Context, obj *entities.ImportedManagedResource) (*model.OnlineStatus, error) { + return &model.OnlineStatus{ + LastOnlineAt: time.Now().Format(time.RFC3339), + WillBeOfflineAt: time.Now().Add(2 * time.Minute).Format(time.RFC3339), + }, nil +} + // CoreCreateEnvironment is the resolver for the core_createEnvironment field. func (r *mutationResolver) CoreCreateEnvironment(ctx context.Context, env entities.Environment) (*entities.Environment, error) { cc, err := toConsoleContext(ctx) @@ -1034,5 +1060,7 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } -type mutationResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } +type ( + mutationResolver struct{ *Resolver } + queryResolver struct{ *Resolver } +) diff --git a/apps/console/internal/app/process-resource-updates.go b/apps/console/internal/app/process-resource-updates.go index 340636a97..9a123a4c1 100644 --- a/apps/console/internal/app/process-resource-updates.go +++ b/apps/console/internal/app/process-resource-updates.go @@ -52,6 +52,9 @@ var ( func ProcessResourceUpdates(consumer ResourceUpdateConsumer, d domain.Domain, logger *slog.Logger) { getResourceContext := func(ctx domain.ConsoleContext, rt entities.ResourceType, clusterName string, obj *unstructured.Unstructured) (domain.ResourceContext, error) { + if v, ok := obj.GetLabels()[constants.EnvNameKey]; ok { + return domain.ResourceContext{ConsoleContext: ctx, EnvironmentName: v}, nil + } mapping, err := d.GetEnvironmentResourceMapping(ctx, rt, clusterName, obj.GetNamespace(), obj.GetName()) if err != nil { return domain.ResourceContext{}, err @@ -119,7 +122,12 @@ func ProcessResourceUpdates(consumer ResourceUpdateConsumer, d domain.Domain, lo mlogger.Info("PROCESSED message", "took", fmt.Sprintf("%dms", time.Since(start).Milliseconds())) }() - dctx := domain.NewConsoleContext(context.TODO(), "sys-user:console-resource-updater", ru.AccountName) + accountName := ru.AccountName + if v, ok := rwu.Object.GetLabels()[constants.AccountNameKey]; ok && len(v) > 0 { + accountName = v + } + + dctx := domain.NewConsoleContext(context.TODO(), "sys-user:console-resource-updater", accountName) resStatus, err := func() (types.ResourceStatus, error) { v, ok := obj.Object[types.ResourceStatusKey] @@ -142,7 +150,6 @@ func ProcessResourceUpdates(consumer ResourceUpdateConsumer, d domain.Domain, lo switch gvkStr { case environmentGVK.String(): { - dctx.AccountName = rwu.Object.GetLabels()[constants.AccountNameKey] var ws entities.Environment if err := fn.JsonConversion(rwu.Object, &ws); err != nil { return errors.NewE(err) @@ -155,18 +162,11 @@ func ProcessResourceUpdates(consumer ResourceUpdateConsumer, d domain.Domain, lo } case appsGVK.String(): { - if ru.AccountName == "nxt-multi-tenancy" { - } - - dctx.AccountName = rwu.Object.GetLabels()[constants.AccountNameKey] - var app entities.App if err := fn.JsonConversion(rwu.Object, &app); err != nil { return errors.NewE(err) } - // rctx := domain.ResourceContext{ConsoleContext: dctx, EnvironmentName: rwu.Object.GetLabels()[constants.EnvNameKey]} - rctx, err := getResourceContext(dctx, entities.ResourceTypeApp, ru.ClusterName, obj) if err != nil { return errors.NewE(err) diff --git a/apps/console/internal/domain/api.go b/apps/console/internal/domain/api.go index fea90a50c..84e161826 100644 --- a/apps/console/internal/domain/api.go +++ b/apps/console/internal/domain/api.go @@ -140,6 +140,12 @@ type AccountsSvc interface { GetAccountRegion(ctx context.Context, userId string, accountName string) (string, error) } +type ResourceDispatcher interface { + ApplyResource() + DeleteResource() + RestartResource() +} + type Domain interface { AccountsSvc diff --git a/apps/console/internal/domain/domain.go b/apps/console/internal/domain/domain.go index d2a088a74..74a4e95a2 100644 --- a/apps/console/internal/domain/domain.go +++ b/apps/console/internal/domain/domain.go @@ -27,10 +27,10 @@ import ( "go.uber.org/fx" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kloudlite/api/apps/console/internal/domain/ports" "github.com/kloudlite/api/apps/console/internal/entities" "github.com/kloudlite/api/apps/console/internal/env" iamT "github.com/kloudlite/api/apps/iam/types" - "github.com/kloudlite/api/grpc-interfaces/infra" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" fn "github.com/kloudlite/api/pkg/functions" "github.com/kloudlite/api/pkg/k8s" @@ -47,7 +47,7 @@ type domain struct { producer MessageDispatcher iamClient iam.IAMClient - infraClient infra.InfraClient + infraSvc ports.InfraService platformEdgeClient platform_edge.PlatformEdgeClient AccountsSvc @@ -105,6 +105,8 @@ func addTrackingId(obj client.Object, id repos.ID) { type K8sContext interface { context.Context GetUserId() repos.ID + GetUserEmail() string + GetUserName() string GetAccountName() string } @@ -131,9 +133,9 @@ func (d *domain) applyK8sResourceOnCluster(ctx K8sContext, clusterName string, o } b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.GetAccountName(), - ClusterName: clusterName, - Action: t.ActionApply, - Object: m, + // ClusterName: clusterName, + Action: t.ActionApply, + Object: m, }) if err != nil { return errors.NewE(err) @@ -167,9 +169,6 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj switch *clusterName { case "__kloudlite_enabled_cluster": { - // dispatchAddr.AccountName = "kloudlite-edge-platform" - // dispatchAddr.ClusterName = "kl-edge-1" - allocatedEdge, err := d.platformEdgeClient.GetAllocatedPlatformEdgeCluster(ctx, &platform_edge.GetAllocatedPlatformEdgeClusterIn{AccountName: ctx.GetAccountName()}) if err != nil { gErr := grpc.ParseErr(err) @@ -194,6 +193,20 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj if err != nil { return errors.NewEf(err, "failed to allocate platform edge cluster") } + + if err := d.infraSvc.EnsureGlobalVPNConnection(ctx, ports.EnsureGlobalVPNConnectionIn{ + UserId: string(ctx.GetUserId()), + UserEmail: ctx.GetUserEmail(), + UserName: ctx.GetUserName(), + AccountName: ctx.GetAccountName(), + ClusterName: allocatedEdge.ClusterName, + GlobalVPNName: "default", + + DispatchAddrAccountName: allocatedEdge.OwnedByAccount, + DispatchAddrClusterName: allocatedEdge.ClusterName, + }); err != nil { + return errors.NewEf(err, "failed to ensure global vpn connection") + } } dispatchAddr.AccountName = allocatedEdge.OwnedByAccount @@ -231,8 +244,7 @@ func (d *domain) applyK8sResource(ctx K8sContext, envName string, obj client.Obj } b, err := json.Marshal(t.AgentMessage{ - AccountName: dispatchAddr.AccountName, - ClusterName: dispatchAddr.ClusterName, + AccountName: ctx.GetAccountName(), Action: t.ActionApply, Object: m, }) @@ -280,7 +292,6 @@ func applyK8sResource(ctx K8sContext, args ApplyK8sResourceArgs) error { } b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.GetAccountName(), - ClusterName: args.ClusterName, Action: t.ActionApply, Object: m, }) @@ -339,7 +350,6 @@ func (d *domain) restartK8sResource(ctx K8sContext, projectName string, namespac b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.GetAccountName(), - ClusterName: *clusterName, Action: t.ActionRestart, Object: obj.Object, }) @@ -367,7 +377,6 @@ func (d *domain) deleteK8sResourceOfCluster(ctx K8sContext, clusterName string, } b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.GetAccountName(), - ClusterName: clusterName, Action: t.ActionDelete, Object: m, }) @@ -429,7 +438,6 @@ func (d *domain) deleteK8sResource(ctx K8sContext, environmentName string, obj c } b, err := json.Marshal(t.AgentMessage{ AccountName: dispatchAddr.AccountName, - ClusterName: dispatchAddr.ClusterName, Action: t.ActionDelete, Object: m, }) @@ -662,7 +670,7 @@ var Module = fx.Module("domain", producer MessageDispatcher, iamClient iam.IAMClient, - infraClient infra.InfraClient, + infraSvc ports.InfraService, platformEdgeClient platform_edge.PlatformEdgeClient, accountsSvc AccountsSvc, @@ -694,7 +702,7 @@ var Module = fx.Module("domain", producer: producer, iamClient: iamClient, - infraClient: infraClient, + infraSvc: infraSvc, platformEdgeClient: platformEdgeClient, AccountsSvc: accountsSvc, diff --git a/apps/console/internal/domain/environments/domain.go b/apps/console/internal/domain/environments/domain.go new file mode 100644 index 000000000..7d3a8b9b7 --- /dev/null +++ b/apps/console/internal/domain/environments/domain.go @@ -0,0 +1,42 @@ +package environments + +import ( + "time" + + "github.com/kloudlite/api/apps/console/internal/domain/types" + "github.com/kloudlite/api/apps/console/internal/entities" + "github.com/kloudlite/api/pkg/repos" + crdsv1 "github.com/kloudlite/operator/apis/crds/v1" + + watcher_types "github.com/kloudlite/operator/operators/resource-watcher/types" +) + +type CloneEnvironmentArgs struct { + SourceEnvName string + DestinationEnvName string + DisplayName string + EnvRoutingMode crdsv1.EnvironmentRoutingMode + ClusterName string +} + +type UpdateAndDeleteOpts struct { + MessageTimestamp time.Time + ClusterName string +} + +type Domain interface { + ListEnvironments(ctx types.ConsoleContext, search map[string]repos.MatchFilter, pq repos.CursorPagination) (*repos.PaginatedRecord[*entities.Environment], error) + GetEnvironment(ctx types.ConsoleContext, name string) (*entities.Environment, error) + + CreateEnvironment(ctx types.ConsoleContext, env entities.Environment) (*entities.Environment, error) + CloneEnvironment(ctx types.ConsoleContext, args CloneEnvironmentArgs) (*entities.Environment, error) + UpdateEnvironment(ctx types.ConsoleContext, env entities.Environment) (*entities.Environment, error) + DeleteEnvironment(ctx types.ConsoleContext, name string) error + ArchiveEnvironmentsForCluster(ctx types.ConsoleContext, clusterName string) (bool, error) +} + +type Sync interface { + OnEnvironmentApplyError(ctx types.ConsoleContext, errMsg, namespace, name string, opts UpdateAndDeleteOpts) error + OnEnvironmentDeleteMessage(ctx types.ConsoleContext, env entities.Environment) error + OnEnvironmentUpdateMessage(ctx types.ConsoleContext, env entities.Environment, status watcher_types.ResourceStatus, opts UpdateAndDeleteOpts) error +} diff --git a/apps/console/internal/domain/environments/errors.go b/apps/console/internal/domain/environments/errors.go new file mode 100644 index 000000000..d4fcbc9f9 --- /dev/null +++ b/apps/console/internal/domain/environments/errors.go @@ -0,0 +1 @@ +package environments diff --git a/apps/console/internal/domain/environments/repo.go b/apps/console/internal/domain/environments/repo.go new file mode 100644 index 000000000..e6a836be2 --- /dev/null +++ b/apps/console/internal/domain/environments/repo.go @@ -0,0 +1,211 @@ +package environments + +// import ( +// "fmt" +// "log/slog" +// "strings" +// +// "github.com/kloudlite/api/apps/console/internal/domain/ports" +// "github.com/kloudlite/api/apps/console/internal/domain/types" +// "github.com/kloudlite/api/apps/console/internal/entities" +// "github.com/kloudlite/api/common" +// "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" +// "github.com/kloudlite/api/pkg/errors" +// "github.com/kloudlite/api/pkg/k8s" +// "github.com/kloudlite/api/pkg/repos" +// +// iamT "github.com/kloudlite/api/apps/iam/types" +// t "github.com/kloudlite/api/pkg/types" +// crdsv1 "github.com/kloudlite/operator/apis/crds/v1" +// ) +// +// type Repo struct { +// logger *slog.Logger +// +// k8sClient k8s.Client +// environmentRepo repos.DbRepo[*entities.Environment] +// +// resourceEventPublisher types.ResourceEventPublisher +// +// iamSvc ports.IAMService +// } +// +// func getEnvironmentTargetNamespace(envName string) string { +// return fmt.Sprintf("env-%s", envName) +// } +// +// // ArchiveEnvironmentsForCluster implements Domain. +// func (r *Repo) ArchiveEnvironmentsForCluster(ctx types.ConsoleContext, clusterName string) (bool, error) { +// panic("unimplemented") +// } +// +// // CloneEnvironment implements Domain. +// func (r *Repo) CloneEnvironment(ctx types.ConsoleContext, args CloneEnvironmentArgs) (*entities.Environment, error) { +// panic("unimplemented") +// } +// +// // CreateEnvironment implements Domain. +// func (r *Repo) CreateEnvironment(ctx types.ConsoleContext, env entities.Environment) (*entities.Environment, error) { +// if strings.TrimSpace(env.ClusterName) == "" { +// return nil, errors.New("clustername must be set while creating environments") +// } +// +// env.EnsureGVK() +// if err := r.k8sClient.ValidateObject(ctx, &env.Environment); err != nil { +// return nil, errors.NewE(err) +// } +// +// env.IncrementRecordVersion() +// +// if env.Spec.TargetNamespace == "" { +// env.Spec.TargetNamespace = getEnvironmentTargetNamespace(env.Name) +// } +// +// if env.Spec.Routing == nil { +// env.Spec.Routing = &crdsv1.EnvironmentRouting{ +// Mode: crdsv1.EnvironmentRoutingModePrivate, +// } +// } +// +// env.CreatedBy = common.CreatedOrUpdatedBy{ +// UserId: ctx.UserId, +// UserName: ctx.UserName, +// UserEmail: ctx.UserEmail, +// } +// env.LastUpdatedBy = env.CreatedBy +// +// env.AccountName = ctx.AccountName +// env.SyncStatus = t.GenSyncStatus(t.SyncActionApply, env.RecordVersion) +// +// nenv, err := r.environmentRepo.Create(ctx, &env) +// if err != nil { +// if r.environmentRepo.ErrAlreadyExists(err) { +// // TODO: better insights into error, when it is being caused by duplicated indexes +// return nil, errors.NewE(err) +// } +// return nil, errors.NewE(err) +// } +// +// // FIXME: this should be setup when actually dispatching resource +// // if _, err := d.upsertEnvironmentResourceMapping(ResourceContext{ConsoleContext: ctx, EnvironmentName: env.Name}, &env); err != nil { +// // return nil, errors.NewE(err) +// // } +// +// r.resourceEventPublisher.PublishConsoleEvent(ctx, entities.ResourceTypeEnvironment, nenv.Name, types.PublishAdd) +// +// if _, err := r.iamSvc.AddMembership(ctx, &iam.AddMembershipIn{ +// UserId: string(ctx.UserId), +// ResourceType: string(iamT.ResourceEnvironment), +// ResourceRef: iamT.NewResourceRef(ctx.AccountName, iamT.ResourceEnvironment, nenv.Name), +// Role: string(iamT.RoleResourceOwner), +// }); err != nil { +// r.logger.Error("while adding membership, got", "err", err) +// } +// +// if err := d.applyEnvironmentTargetNamespace(ctx, nenv); err != nil { +// return nil, errors.NewE(err) +// } +// +// if err := d.applyK8sResource(ctx, nenv.Name, &nenv.Environment, nenv.RecordVersion); err != nil { +// return nil, errors.NewE(err) +// } +// +// if err := d.syncImagePullSecretsToEnvironment(ctx, nenv.Name); err != nil { +// return nil, errors.NewE(err) +// } +// +// return nenv, nil +// } +// +// // func (d *domain) CreateEnvironment(ctx ConsoleContext, env entities.Environment) (*entities.Environment, error) { +// // if strings.TrimSpace(env.ClusterName) == "" { +// // return nil, fmt.Errorf("clustername must be set while creating environments") +// // } +// // +// // env.EnsureGVK() +// // if err := d.k8sClient.ValidateObject(ctx, &env.Environment); err != nil { +// // return nil, errors.NewE(err) +// // } +// // +// // env.IncrementRecordVersion() +// // +// // if env.Spec.TargetNamespace == "" { +// // env.Spec.TargetNamespace = d.getEnvironmentTargetNamespace(env.Name) +// // } +// // +// // if env.Spec.Routing == nil { +// // env.Spec.Routing = &crdsv1.EnvironmentRouting{ +// // Mode: crdsv1.EnvironmentRoutingModePrivate, +// // } +// // } +// // +// // env.CreatedBy = common.CreatedOrUpdatedBy{ +// // UserId: ctx.UserId, +// // UserName: ctx.UserName, +// // UserEmail: ctx.UserEmail, +// // } +// // env.LastUpdatedBy = env.CreatedBy +// // +// // env.AccountName = ctx.AccountName +// // env.SyncStatus = t.GenSyncStatus(t.SyncActionApply, env.RecordVersion) +// // +// // nenv, err := d.environmentRepo.Create(ctx, &env) +// // if err != nil { +// // if d.environmentRepo.ErrAlreadyExists(err) { +// // // TODO: better insights into error, when it is being caused by duplicated indexes +// // return nil, errors.NewE(err) +// // } +// // return nil, errors.NewE(err) +// // } +// // +// // if _, err := d.upsertEnvironmentResourceMapping(ResourceContext{ConsoleContext: ctx, EnvironmentName: env.Name}, &env); err != nil { +// // return nil, errors.NewE(err) +// // } +// // +// // d.resourceEventPublisher.PublishConsoleEvent(ctx, entities.ResourceTypeEnvironment, nenv.Name, PublishAdd) +// // +// // if _, err := d.iamClient.AddMembership(ctx, &iam.AddMembershipIn{ +// // UserId: string(ctx.UserId), +// // ResourceType: string(iamT.ResourceEnvironment), +// // ResourceRef: iamT.NewResourceRef(ctx.AccountName, iamT.ResourceEnvironment, nenv.Name), +// // Role: string(iamT.RoleResourceOwner), +// // }); err != nil { +// // d.logger.Errorf(err, "error while adding membership") +// // } +// // +// // if err := d.applyEnvironmentTargetNamespace(ctx, nenv); err != nil { +// // return nil, errors.NewE(err) +// // } +// // +// // if err := d.applyK8sResource(ctx, nenv.Name, &nenv.Environment, nenv.RecordVersion); err != nil { +// // return nil, errors.NewE(err) +// // } +// // +// // if err := d.syncImagePullSecretsToEnvironment(ctx, nenv.Name); err != nil { +// // return nil, errors.NewE(err) +// // } +// // +// // return nenv, nil +// // } +// +// // DeleteEnvironment implements Domain. +// func (r *Repo) DeleteEnvironment(ctx types.ConsoleContext, name string) error { +// panic("unimplemented") +// } +// +// // GetEnvironment implements Domain. +// func (r *Repo) GetEnvironment(ctx types.ConsoleContext, name string) (*entities.Environment, error) { +// panic("unimplemented") +// } +// +// // ListEnvironments implements Domain. +// func (r *Repo) ListEnvironments(ctx types.ConsoleContext, search map[string]repos.MatchFilter, pq repos.CursorPagination) (*repos.PaginatedRecord[*entities.Environment], error) { +// panic("unimplemented") +// } +// +// // UpdateEnvironment implements Domain. +// func (r *Repo) UpdateEnvironment(ctx types.ConsoleContext, env entities.Environment) (*entities.Environment, error) { +// panic("unimplemented") +// } +// +// var _ Domain = (*Repo)(nil) diff --git a/apps/console/internal/domain/environments/repo_test.go b/apps/console/internal/domain/environments/repo_test.go new file mode 100644 index 000000000..d4fcbc9f9 --- /dev/null +++ b/apps/console/internal/domain/environments/repo_test.go @@ -0,0 +1 @@ +package environments diff --git a/apps/console/internal/domain/kloudlite-edge-cluster/domain.go b/apps/console/internal/domain/kloudlite-edge-cluster/domain.go deleted file mode 100644 index 86791723e..000000000 --- a/apps/console/internal/domain/kloudlite-edge-cluster/domain.go +++ /dev/null @@ -1,9 +0,0 @@ -package kloudlite_edge_cluster - -import "context" - -type PickEdgeClusterArgs struct{} - -func PickEdgeCluster(ctx context.Context, args *PickEdgeClusterArgs) (any, error) { - return nil, nil -} diff --git a/apps/console/internal/domain/ports/iam-service.go b/apps/console/internal/domain/ports/iam-service.go new file mode 100644 index 000000000..bb1340219 --- /dev/null +++ b/apps/console/internal/domain/ports/iam-service.go @@ -0,0 +1,20 @@ +package ports + +import ( + "context" + + "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" +) + +type IAMService interface { + AddMembership(ctx context.Context, in *iam.AddMembershipIn) (*iam.AddMembershipOut, error) + // Can(ctx context.Context, in *CanIn, opts ...grpc.CallOption) (*CanOut, error) + // ListMembershipsForResource(ctx context.Context, in *MembershipsForResourceIn, opts ...grpc.CallOption) (*ListMembershipsOut, error) + // ListMembershipsForUser(ctx context.Context, in *MembershipsForUserIn, opts ...grpc.CallOption) (*ListMembershipsOut, error) + // GetMembership(ctx context.Context, in *GetMembershipIn, opts ...grpc.CallOption) (*GetMembershipOut, error) + // // Mutation + // AddMembership(ctx context.Context, in *AddMembershipIn, opts ...grpc.CallOption) (*AddMembershipOut, error) + // UpdateMembership(ctx context.Context, in *UpdateMembershipIn, opts ...grpc.CallOption) (*UpdateMembershipOut, error) + // RemoveMembership(ctx context.Context, in *RemoveMembershipIn, opts ...grpc.CallOption) (*RemoveMembershipOut, error) + // RemoveResource(ctx context.Context, in *RemoveResourceIn, opts ...grpc.CallOption) (*RemoveResourceOut, error) +} diff --git a/apps/console/internal/domain/ports/infra-service.go b/apps/console/internal/domain/ports/infra-service.go new file mode 100644 index 000000000..c3ea80100 --- /dev/null +++ b/apps/console/internal/domain/ports/infra-service.go @@ -0,0 +1,20 @@ +package ports + +import "context" + +type InfraService interface { + EnsureGlobalVPNConnection(ctx context.Context, args EnsureGlobalVPNConnectionIn) error +} + +type EnsureGlobalVPNConnectionIn struct { + UserId string + UserEmail string + UserName string + + AccountName string + ClusterName string + GlobalVPNName string + + DispatchAddrAccountName string + DispatchAddrClusterName string +} diff --git a/apps/console/internal/domain/ports/resource-dispatch.go b/apps/console/internal/domain/ports/resource-dispatch.go new file mode 100644 index 000000000..4d5829d8c --- /dev/null +++ b/apps/console/internal/domain/ports/resource-dispatch.go @@ -0,0 +1,15 @@ +package ports + +// import ( +// "sigs.k8s.io/controller-runtime/pkg/client" +// ) +// +// type ResourceDispatcher interface { +// ApplyResource(ctx InfraContext, clusterName string, obj client.Object, recordVersion int) error +// DeleteResource(ctx InfraContext, clusterName string, obj client.Object) error +// RestartResource(ctx InfraContext, clusterName string, obj client.Object) error +// } +// +// type ResourceUpdatesReceiver interface { +// OnResourceUpdate(ctx InfraContext, clusterName string, obj client.Object, recordVersion int) error +// } diff --git a/apps/console/internal/domain/types/event-publisher.go b/apps/console/internal/domain/types/event-publisher.go new file mode 100644 index 000000000..508b61730 --- /dev/null +++ b/apps/console/internal/domain/types/event-publisher.go @@ -0,0 +1,18 @@ +package types + +import "github.com/kloudlite/api/apps/console/internal/entities" + +type PublishMsg string + +const ( + PublishAdd PublishMsg = "added" + PublishDelete PublishMsg = "deleted" + PublishUpdate PublishMsg = "updated" +) + +type ResourceEventPublisher interface { + PublishConsoleEvent(ctx ConsoleContext, resourceType entities.ResourceType, name string, update PublishMsg) + PublishEnvironmentResourceEvent(ctx ConsoleContext, envName string, resourceType entities.ResourceType, name string, update PublishMsg) + PublishResourceEvent(ctx ResourceContext, resourceType entities.ResourceType, name string, update PublishMsg) + PublishClusterManagedServiceEvent(ctx ConsoleContext, msvcName string, resourceType entities.ResourceType, name string, update PublishMsg) +} diff --git a/apps/console/internal/domain/types/types.go b/apps/console/internal/domain/types/types.go new file mode 100644 index 000000000..23bf37d34 --- /dev/null +++ b/apps/console/internal/domain/types/types.go @@ -0,0 +1,43 @@ +package types + +import ( + "context" + + "github.com/kloudlite/api/pkg/repos" +) + +type ConsoleContext struct { + context.Context + AccountName string + + UserId repos.ID + UserEmail string + UserName string +} + +func (c ConsoleContext) GetUserId() repos.ID { + return c.UserId +} + +func (c ConsoleContext) GetUserEmail() string { + return c.UserEmail +} + +func (c ConsoleContext) GetUserName() string { + return c.UserName +} + +func (c ConsoleContext) GetAccountName() string { + return c.AccountName +} + +type ResourceContext struct { + ConsoleContext + EnvironmentName string +} + +type ManagedResourceContext struct { + ConsoleContext + ManagedServiceName *string + EnvironmentName *string +} diff --git a/apps/console/internal/entities/environment.go b/apps/console/internal/entities/environment.go index d558970b4..291c7ad8b 100644 --- a/apps/console/internal/entities/environment.go +++ b/apps/console/internal/entities/environment.go @@ -22,7 +22,7 @@ type Environment struct { common.ResourceMetadata `json:",inline"` - SyncStatus t.SyncStatus `json:"syncStatus" graphql:"noinput"` + SyncStatus t.SyncStatus `json:"syncStatus" graphql:"noinput"` } func (e *Environment) GetDisplayName() string { diff --git a/apps/console/main.go b/apps/console/main.go index 66a5fdb6b..10fbee98d 100644 --- a/apps/console/main.go +++ b/apps/console/main.go @@ -3,7 +3,6 @@ package main import ( "context" "flag" - "log/slog" "os" "time" @@ -20,6 +19,9 @@ import ( ) func main() { + start := time.Now() + common.PrintBuildInfo() + var isDev bool flag.BoolVar(&isDev, "dev", false, "--dev") @@ -32,22 +34,15 @@ func main() { debug = true } - common.PrintBuildInfo() - logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug, SetAsDefaultLogger: true}) - start := time.Now() - app := fx.New( - fx.StartTimeout(5*time.Second), fx.NopLogger, fx.Provide(func() (logging.Logger, error) { return logging.New(&logging.Options{Name: "console", ShowDebugLog: debug}) }), - fx.Provide(func() *slog.Logger { - return logger - }), + fx.Supply(logger), fx.Provide(func() (*env.Env, error) { if e, err := env.LoadEnv(); err != nil { @@ -59,7 +54,7 @@ func main() { }), fx.Provide(func(e *env.Env) (*rest.Config, error) { - if e.KubernetesApiProxy != "" { + if isDev && e.KubernetesApiProxy != "" { return &rest.Config{ Host: e.KubernetesApiProxy, }, nil @@ -71,9 +66,9 @@ func main() { ctx, cancelFunc := func() (context.Context, context.CancelFunc) { if isDev { - return context.WithTimeout(context.TODO(), 5*time.Second) + return context.WithTimeout(context.TODO(), 10*time.Second) } - return context.WithTimeout(context.TODO(), 10*time.Second) + return context.WithTimeout(context.TODO(), 5*time.Second) }() defer cancelFunc() From f3628f0a2e5450b8330edcff96ea188a2bf4484f Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Sat, 14 Sep 2024 02:30:49 +0530 Subject: [PATCH 10/17] feat(infra): adds support for gateway creation on kloudlite edge clusters --- apps/infra/Taskfile.yml | 6 + .../internal/app/adapter-resource-apply.go | 25 +- .../app/adapters/message-office-svc.go | 84 ++ apps/infra/internal/app/app.go | 19 +- apps/infra/internal/app/grpc-server.go | 36 +- .../internal/app/process-error-on-apply.go | 4 +- .../internal/app/process-resource-updates.go | 12 +- apps/infra/internal/domain/api.go | 3 +- apps/infra/internal/domain/byok-clusters.go | 2 +- apps/infra/internal/domain/clusters.go | 215 +++- apps/infra/internal/domain/domain.go | 59 +- .../domain/global-vpn-cluster-connection.go | 66 +- .../internal/domain/global-vpn-devices.go | 2 +- apps/infra/internal/domain/global-vpn.go | 2 +- apps/infra/internal/domain/helm-release.go | 12 +- apps/infra/internal/domain/nodepool.go | 14 +- apps/infra/internal/domain/ports.go | 6 +- .../domain/ports/message-office-svc.go | 38 + apps/infra/internal/domain/pv.go | 2 +- apps/infra/internal/domain/templates/types.go | 16 +- .../field-constants/generated_constants.go | 63 +- .../entities/global-vpn-connection.go | 24 +- apps/infra/internal/entities/helm-release.go | 2 + apps/infra/internal/entities/nodepool.go | 2 + apps/infra/internal/framework/framework.go | 3 +- apps/infra/main.go | 27 +- apps/infra/protobufs/infra.proto | 87 ++ apps/infra/protobufs/infra/infra.pb.go | 1060 +++++++++++++++++ apps/infra/protobufs/infra/infra_grpc.pb.go | 294 +++++ 29 files changed, 2025 insertions(+), 160 deletions(-) create mode 100644 apps/infra/internal/app/adapters/message-office-svc.go create mode 100644 apps/infra/internal/domain/ports/message-office-svc.go create mode 100644 apps/infra/protobufs/infra.proto create mode 100644 apps/infra/protobufs/infra/infra.pb.go create mode 100644 apps/infra/protobufs/infra/infra_grpc.pb.go diff --git a/apps/infra/Taskfile.yml b/apps/infra/Taskfile.yml index f06c4d83f..c16798cd5 100644 --- a/apps/infra/Taskfile.yml +++ b/apps/infra/Taskfile.yml @@ -15,6 +15,11 @@ tasks: - go run github.com/99designs/gqlgen generate - gofmt -w -d -r '"errors" -> "github.com/kloudlite/api/pkg/errors"' graph/*.resolvers.go + protobufs: + dir: ./protobufs/ + cmds: + - protoc --go_out=. --go-grpc_out=. --go_opt=paths=import --go-grpc_opt=paths=import ./*.proto + k8s-schema: cmds: - mkdir -p "./internal/app/_struct-to-graphql" @@ -56,6 +61,7 @@ tasks: build: cmds: + - task: protobufs - task: gen:constants - task: go:build vars: diff --git a/apps/infra/internal/app/adapter-resource-apply.go b/apps/infra/internal/app/adapter-resource-apply.go index 228cb632a..9e6660eef 100644 --- a/apps/infra/internal/app/adapter-resource-apply.go +++ b/apps/infra/internal/app/adapter-resource-apply.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/kloudlite/api/apps/infra/internal/domain" + "github.com/kloudlite/api/apps/infra/internal/entities" t "github.com/kloudlite/api/apps/tenant-agent/types" "github.com/kloudlite/api/common" "github.com/kloudlite/api/pkg/errors" @@ -27,7 +28,7 @@ func NewResourceDispatcher(producer SendTargetClusterMessagesProducer) domain.Re } } -func (a *resourceDispatcherImpl) ApplyToTargetCluster(ctx domain.InfraContext, clusterName string, obj client.Object, recordVersion int) error { +func (a *resourceDispatcherImpl) ApplyToTargetCluster(ctx domain.InfraContext, dispatchAddr *entities.DispatchAddr, obj client.Object, recordVersion int) error { ann := obj.GetAnnotations() if ann == nil { ann = make(map[string]string, 1) @@ -40,9 +41,15 @@ func (a *resourceDispatcherImpl) ApplyToTargetCluster(ctx domain.InfraContext, c return errors.NewE(err) } + lb := obj.GetLabels() + if lb == nil { + lb = make(map[string]string, 1) + } + lb[constants.AccountNameKey] = ctx.AccountName + obj.SetLabels(lb) + b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.AccountName, - ClusterName: clusterName, Action: t.ActionApply, Object: m, }) @@ -51,22 +58,28 @@ func (a *resourceDispatcherImpl) ApplyToTargetCluster(ctx domain.InfraContext, c } err = a.producer.Produce(ctx, msgTypes.ProduceMsg{ - Subject: common.SendToAgentSubjectName(ctx.AccountName, clusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()), + Subject: common.SendToAgentSubjectName(dispatchAddr.AccountName, dispatchAddr.ClusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()), Payload: b, }) return errors.NewE(err) } -func (d *resourceDispatcherImpl) DeleteFromTargetCluster(ctx domain.InfraContext, clusterName string, obj client.Object) error { +func (d *resourceDispatcherImpl) DeleteFromTargetCluster(ctx domain.InfraContext, dispatchAddr *entities.DispatchAddr, obj client.Object) error { m, err := fn.K8sObjToMap(obj) if err != nil { return errors.NewE(err) } + lb := obj.GetLabels() + if lb == nil { + lb = make(map[string]string, 1) + } + lb[constants.AccountNameKey] = ctx.AccountName + obj.SetLabels(lb) + b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.AccountName, - ClusterName: clusterName, Action: t.ActionDelete, Object: m, }) @@ -75,7 +88,7 @@ func (d *resourceDispatcherImpl) DeleteFromTargetCluster(ctx domain.InfraContext } err = d.producer.Produce(ctx, msgTypes.ProduceMsg{ - Subject: common.SendToAgentSubjectName(ctx.AccountName, clusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()), + Subject: common.SendToAgentSubjectName(dispatchAddr.AccountName, dispatchAddr.ClusterName, obj.GetObjectKind().GroupVersionKind().String(), obj.GetNamespace(), obj.GetName()), Payload: b, }) diff --git a/apps/infra/internal/app/adapters/message-office-svc.go b/apps/infra/internal/app/adapters/message-office-svc.go new file mode 100644 index 000000000..357c0306f --- /dev/null +++ b/apps/infra/internal/app/adapters/message-office-svc.go @@ -0,0 +1,84 @@ +package adapters + +import ( + "context" + + "github.com/kloudlite/api/apps/infra/internal/domain/ports" + cluster_token "github.com/kloudlite/api/apps/message-office/protobufs/cluster-token" + platform_edge "github.com/kloudlite/api/apps/message-office/protobufs/platform-edge" + "github.com/kloudlite/api/pkg/errors" + "github.com/kloudlite/api/pkg/grpc" + "go.uber.org/fx" +) + +type MesasageOfficeGRPCClient grpc.Client + +type MessageOfficeService struct { + clusterTokenClient cluster_token.ClusterTokenClient + platformEdgeClient platform_edge.PlatformEdgeClient +} + +// GenerateClusterToken implements ports.MessageOfficeService. +func (m *MessageOfficeService) GenerateClusterToken(ctx context.Context, in *ports.GenerateClusterTokenIn) (*ports.GenerateClusterTokenOut, error) { + tout, err := m.clusterTokenClient.GenerateClusterToken(ctx, &cluster_token.GenerateClusterTokenIn{ + AccountName: in.AccountName, + ClusterName: in.ClusterName, + }) + if err != nil { + return nil, errors.NewE(err) + } + + return &ports.GenerateClusterTokenOut{ClusterToken: tout.ClusterToken}, nil +} + +// GetAllocatedPlatformEdgeCluster implements ports.MessageOfficeService. +func (m *MessageOfficeService) GetAllocatedPlatformEdgeCluster(ctx context.Context, args *ports.GetAllocatedPlatformEdgeClusterIn) (*ports.GetAllocatedPlatformEdgeClusterOut, error) { + out, err := m.platformEdgeClient.GetAllocatedPlatformEdgeCluster(ctx, &platform_edge.GetAllocatedPlatformEdgeClusterIn{ + AccountName: args.AccountName, + ClusterName: args.ClusterName, + }) + if err != nil { + return nil, err + } + + return &ports.GetAllocatedPlatformEdgeClusterOut{ + PublicDNSHost: out.GetPublicDnsHost(), + }, nil +} + +// GetClusterToken implements ports.MessageOfficeService. +func (m *MessageOfficeService) GetClusterToken(ctx context.Context, in *ports.GetClusterTokenIn) (*ports.GetClusterTokenOut, error) { + tout, err := m.clusterTokenClient.GetClusterToken(ctx, &cluster_token.GetClusterTokenIn{ + AccountName: in.AccountName, + ClusterName: in.ClusterName, + }) + if err != nil { + return nil, errors.NewE(err) + } + + return &ports.GetClusterTokenOut{ClusterToken: tout.ClusterToken}, nil +} + +var _ ports.MessageOfficeService = (*MessageOfficeService)(nil) + +func NewMessageOfficeService(client MesasageOfficeGRPCClient) ports.MessageOfficeService { + return &MessageOfficeService{ + clusterTokenClient: cluster_token.NewClusterTokenClient(client), + platformEdgeClient: platform_edge.NewPlatformEdgeClient(client), + } +} + +func FxNewMessageOfficeService() fx.Option { + return fx.Module("message_office_service", + fx.Provide(func(client MesasageOfficeGRPCClient) ports.MessageOfficeService { + return NewMessageOfficeService(client) + }), + fx.Invoke(func(lf fx.Lifecycle, client MesasageOfficeGRPCClient) { + lf.Append(fx.Hook{ + OnStop: func(ctx context.Context) error { + return client.Close() + }, + }) + }), + ) +} diff --git a/apps/infra/internal/app/app.go b/apps/infra/internal/app/app.go index b9a405537..039210b57 100644 --- a/apps/infra/internal/app/app.go +++ b/apps/infra/internal/app/app.go @@ -11,16 +11,16 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/gofiber/fiber/v2" + "github.com/kloudlite/api/apps/infra/internal/app/adapters" "github.com/kloudlite/api/apps/infra/internal/app/graph" "github.com/kloudlite/api/apps/infra/internal/app/graph/generated" "github.com/kloudlite/api/apps/infra/internal/domain" "github.com/kloudlite/api/apps/infra/internal/env" + "github.com/kloudlite/api/apps/infra/protobufs/infra" "github.com/kloudlite/api/common" "github.com/kloudlite/api/constants" - "github.com/kloudlite/api/grpc-interfaces/infra" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/accounts" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" - message_office_internal "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/message-office-internal" "github.com/kloudlite/api/pkg/grpc" httpServer "github.com/kloudlite/api/pkg/http-server" "github.com/kloudlite/api/pkg/k8s" @@ -35,10 +35,9 @@ import ( type AuthCacheClient kv.Client type ( - IAMGrpcClient grpc.Client - AccountGrpcClient grpc.Client - MessageOfficeInternalGrpcClient grpc.Client - ConsoleGrpcClient grpc.Client + IAMGrpcClient grpc.Client + AccountGrpcClient grpc.Client + ConsoleGrpcClient grpc.Client ) type ( @@ -82,9 +81,7 @@ var Module = fx.Module( return NewAccountsSvc(ac), nil }), - fx.Provide(func(client MessageOfficeInternalGrpcClient) message_office_internal.MessageOfficeInternalClient { - return message_office_internal.NewMessageOfficeInternalClient(client) - }), + adapters.FxNewMessageOfficeService(), fx.Provide( func(conn ConsoleGrpcClient) console.ConsoleClient { @@ -114,8 +111,8 @@ var Module = fx.Module( domain.Module, - fx.Provide(func(d domain.Domain, kcli k8s.Client) infra.InfraServer { - return newGrpcServer(d, kcli) + fx.Provide(func(d domain.Domain, kcli k8s.Client, logger *slog.Logger) infra.InfraServer { + return newGrpcServer(d, kcli, logger) }), fx.Invoke(func(gserver InfraGrpcServer, srv infra.InfraServer) { diff --git a/apps/infra/internal/app/grpc-server.go b/apps/infra/internal/app/grpc-server.go index ef9dca763..73395dc88 100644 --- a/apps/infra/internal/app/grpc-server.go +++ b/apps/infra/internal/app/grpc-server.go @@ -2,11 +2,14 @@ package app import ( "context" + "log/slog" "github.com/kloudlite/api/apps/infra/internal/domain" - "github.com/kloudlite/api/grpc-interfaces/infra" + "github.com/kloudlite/api/apps/infra/internal/entities" + "github.com/kloudlite/api/apps/infra/protobufs/infra" "github.com/kloudlite/api/pkg/errors" fn "github.com/kloudlite/api/pkg/functions" + "github.com/kloudlite/api/pkg/grpc" "github.com/kloudlite/api/pkg/k8s" "github.com/kloudlite/api/pkg/repos" corev1 "k8s.io/api/core/v1" @@ -15,7 +18,29 @@ import ( type grpcServer struct { d domain.Domain infra.UnimplementedInfraServer - kcli k8s.Client + kcli k8s.Client + logger *slog.Logger +} + +// EnsureGlobalVPNConnection implements infra.InfraServer. +func (g *grpcServer) EnsureGlobalVPNConnection(ctx context.Context, in *infra.EnsureGlobalVPNConnectionIn) (*infra.EnsureGlobalVPNConnectionOut, error) { + l := grpc.NewRequestLogger(g.logger, "EnsureGlobalVPNConnection") + defer l.End() + _, err := g.d.EnsureGlobalVPNConnection(domain.InfraContext{ + Context: ctx, + UserId: repos.ID(in.UserId), + UserEmail: in.UserEmail, + UserName: in.UserName, + AccountName: in.AccountName, + }, in.ClusterName, in.GlobalVPNName, &entities.DispatchAddr{ + AccountName: in.DispatchAddr_AccountName, + ClusterName: in.DispatchAddr_ClusterName, + }) + if err != nil { + return nil, errors.NewE(err) + } + + return &infra.EnsureGlobalVPNConnectionOut{}, nil } // GetClusterKubeconfig implements infra.InfraServer. @@ -138,9 +163,10 @@ func (g *grpcServer) MarkClusterOnlineAt(ctx context.Context, in *infra.MarkClus return &infra.MarkClusterOnlineAtOut{}, nil } -func newGrpcServer(d domain.Domain, kcli k8s.Client) infra.InfraServer { +func newGrpcServer(d domain.Domain, kcli k8s.Client, logger *slog.Logger) infra.InfraServer { return &grpcServer{ - d: d, - kcli: kcli, + d: d, + kcli: kcli, + logger: logger, } } diff --git a/apps/infra/internal/app/process-error-on-apply.go b/apps/infra/internal/app/process-error-on-apply.go index 43d85a050..51a55e8c1 100644 --- a/apps/infra/internal/app/process-error-on-apply.go +++ b/apps/infra/internal/app/process-error-on-apply.go @@ -53,7 +53,7 @@ func ProcessErrorOnApply(consumer ErrorOnApplyConsumer, logger *slog.Logger, d d "GVK", gvkStr, "NN", fmt.Sprintf("%s/%s", obj.GetNamespace(), obj.GetName()), "account", errObj.AccountName, - "cluster", errObj.ClusterName, + "cluster", em.ClusterName, ) if len(strings.TrimSpace(errObj.AccountName)) == 0 { @@ -61,7 +61,7 @@ func ProcessErrorOnApply(consumer ErrorOnApplyConsumer, logger *slog.Logger, d d return nil } - if len(strings.TrimSpace(errObj.ClusterName)) == 0 { + if len(strings.TrimSpace(em.ClusterName)) == 0 { mlogger.Warn("message does not contain 'clusterName', so won't be able to find a resource uniquely, thus ignoring ...") return nil } diff --git a/apps/infra/internal/app/process-resource-updates.go b/apps/infra/internal/app/process-resource-updates.go index 351d40abd..01631df1d 100644 --- a/apps/infra/internal/app/process-resource-updates.go +++ b/apps/infra/internal/app/process-resource-updates.go @@ -9,6 +9,7 @@ import ( "sync" "time" + "github.com/kloudlite/api/constants" "github.com/kloudlite/api/pkg/errors" "github.com/kloudlite/api/apps/infra/internal/domain" @@ -88,8 +89,6 @@ func processResourceUpdates(consumer ReceiveResourceUpdatesConsumer, d domain.Do return nil } - dctx := domain.InfraContext{Context: context.TODO(), UserId: "sys-user-process-infra-updates", AccountName: ru.AccountName} - obj := su.Object gvkStr := obj.GetObjectKind().GroupVersionKind().String() @@ -110,6 +109,13 @@ func processResourceUpdates(consumer ReceiveResourceUpdatesConsumer, d domain.Do return nil } + dctx := domain.InfraContext{Context: context.TODO(), UserId: "sys-user-process-infra-updates", AccountName: ru.AccountName} + + if strings.HasPrefix(ru.AccountName, "kl-") { + // FIXME: this is a kloudlite account, so we should handle it differently, as it is definitely not a tenant account + dctx.AccountName = obj.GetLabels()[constants.AccountNameKey] + } + mlogger.Debug("validated message") defer func() { mlogger.Info("PROCESSED message", "took", fmt.Sprintf("%dms", time.Since(start).Milliseconds())) @@ -162,7 +168,7 @@ func processResourceUpdates(consumer ReceiveResourceUpdatesConsumer, d domain.Do if resStatus == types.ResourceStatusDeleted { return d.OnGlobalVPNConnectionDeleteMessage(dctx, ru.ClusterName, gvpn) } - return d.OnGlobalVPNConnectionUpdateMessage(dctx, ru.ClusterName, gvpn, resStatus, domain.UpdateAndDeleteOpts{MessageTimestamp: msg.Timestamp}) + return d.OnGlobalVPNConnectionUpdateMessage(dctx, entities.DispatchAddr{AccountName: ru.AccountName, ClusterName: ru.ClusterName}, gvpn, resStatus, domain.UpdateAndDeleteOpts{MessageTimestamp: msg.Timestamp}) } case nodepoolGVK.String(): diff --git a/apps/infra/internal/domain/api.go b/apps/infra/internal/domain/api.go index 9279f1828..4dc22ba41 100644 --- a/apps/infra/internal/domain/api.go +++ b/apps/infra/internal/domain/api.go @@ -122,9 +122,10 @@ type Domain interface { OnNodepoolApplyError(ctx InfraContext, clusterName string, name string, errMsg string, opts UpdateAndDeleteOpts) error // ListGlobalVPNs(ctx InfraContext, clusterName string) (*entities.GlobalVPNConnection, error) + EnsureGlobalVPNConnection(ctx InfraContext, clusterName string, groupName string, dispatchAddr *entities.DispatchAddr) (*entities.GlobalVPNConnection, error) OnGlobalVPNConnectionDeleteMessage(ctx InfraContext, clusterName string, clusterConn entities.GlobalVPNConnection) error - OnGlobalVPNConnectionUpdateMessage(ctx InfraContext, clusterName string, clusterConn entities.GlobalVPNConnection, status types.ResourceStatus, opts UpdateAndDeleteOpts) error + OnGlobalVPNConnectionUpdateMessage(ctx InfraContext, dispatchAddr entities.DispatchAddr, clusterConn entities.GlobalVPNConnection, status types.ResourceStatus, opts UpdateAndDeleteOpts) error OnGlobalVPNConnectionApplyError(ctx InfraContext, clusterName string, name string, errMsg string, opts UpdateAndDeleteOpts) error ListNodes(ctx InfraContext, clusterName string, search map[string]repos.MatchFilter, pagination repos.CursorPagination) (*repos.PaginatedRecord[*entities.Node], error) diff --git a/apps/infra/internal/domain/byok-clusters.go b/apps/infra/internal/domain/byok-clusters.go index 32383757e..83575b958 100644 --- a/apps/infra/internal/domain/byok-clusters.go +++ b/apps/infra/internal/domain/byok-clusters.go @@ -82,7 +82,7 @@ func (d *domain) CreateBYOKCluster(ctx InfraContext, cluster entities.BYOKCluste cluster.MessageQueueTopicName = common.SendToAgentSubjectPrefix(ctx.AccountName, cluster.Name) - gvpnConn, err := d.ensureGlobalVPNConnection(ctx, cluster.Name, cluster.GlobalVPN) + gvpnConn, err := d.ensureGlobalVPNConnection(ctx, cluster.Name, cluster.GlobalVPN, nil) if err != nil { return nil, errors.NewE(err) } diff --git a/apps/infra/internal/domain/clusters.go b/apps/infra/internal/domain/clusters.go index 18527d2cb..30d42f9b2 100644 --- a/apps/infra/internal/domain/clusters.go +++ b/apps/infra/internal/domain/clusters.go @@ -9,12 +9,12 @@ import ( "time" iamT "github.com/kloudlite/api/apps/iam/types" + "github.com/kloudlite/api/apps/infra/internal/domain/ports" "github.com/kloudlite/api/apps/infra/internal/domain/templates" fc "github.com/kloudlite/api/apps/infra/internal/entities/field-constants" "github.com/kloudlite/api/common" "github.com/kloudlite/api/common/fields" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/console" - message_office_internal "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/message-office-internal" ct "github.com/kloudlite/operator/apis/common-types" "github.com/kloudlite/operator/operators/resource-watcher/types" "github.com/kloudlite/operator/pkg/kubectl" @@ -55,7 +55,7 @@ const ( ) func (d *domain) generateClusterToken(ctx InfraContext, clusterName string) (string, error) { - tout, err := d.messageOfficeInternalClient.GenerateClusterToken(ctx, &message_office_internal.GenerateClusterTokenIn{ + tout, err := d.moSvc.GenerateClusterToken(ctx, &ports.GenerateClusterTokenIn{ AccountName: ctx.AccountName, ClusterName: clusterName, }) @@ -343,7 +343,7 @@ func (d *domain) CreateCluster(ctx InfraContext, cluster entities.Cluster) (*ent cluster.SyncStatus = t.GenSyncStatus(t.SyncActionApply, 0) // FIXME: removing public DNS host for now - gvpnConn, err := d.ensureGlobalVPNConnection(ctx, cluster.Name, *cluster.GlobalVPN) + gvpnConn, err := d.ensureGlobalVPNConnection(ctx, cluster.Name, *cluster.GlobalVPN, nil) if err != nil { return nil, errors.NewE(err) } @@ -378,7 +378,191 @@ func (d *domain) CreateCluster(ctx InfraContext, cluster entities.Cluster) (*ent func (d *domain) syncKloudliteGatewayDevice(ctx InfraContext, gvpnName string) error { t := time.Now() defer func() { - d.logger.Infof("syncKloudliteGatewayDevice took %.2fs", time.Since(t).Seconds()) + d.logger.Info("syncKloudliteGatewayDevice", "took", fmt.Sprintf("%.2fs", time.Since(t).Seconds())) + }() + // 1. parse deployment template + b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) + if err != nil { + return errors.NewE(err) + } + + svcTemplate, err := templates.Read(templates.GatewayServiceTemplate) + if err != nil { + return errors.NewE(err) + } + + accNs := fmt.Sprintf("kl-%s", ctx.AccountName) + + // accNs, err := d.getAccNamespace(ctx) + // if err != nil { + // return errors.NewE(err) + // } + + gv, err := d.findGlobalVPN(ctx, gvpnName) + if err != nil { + return err + } + + if gv.KloudliteGatewayDevice.Name == "" { + return nil + } + + gvpnConns, err := d.listGlobalVPNConnections(ctx, gvpnName) + if err != nil { + return err + } + + klDevice, err := d.findGlobalVPNDevice(ctx, gvpnName, gv.KloudliteGatewayDevice.Name) + if err != nil { + return err + } + + clDevice, err := d.findGlobalVPNDevice(ctx, gvpnName, gv.KloudliteClusterLocalDevice.Name) + if err != nil { + return err + } + + wgParams, deviceHosts, err := d.buildGlobalVPNDeviceWgBaseParams(ctx, gvpnConns, klDevice) + if err != nil { + return err + } + + publicPeers := make([]wgutils.PublicPeer, 0, len(wgParams.PublicPeers)) + for _, p := range wgParams.PublicPeers { + if p.PublicKey != clDevice.PublicKey { + publicPeers = append(publicPeers, p) + } + } + + deviceSvcHosts := make([]string, 0, len(deviceHosts)) + for k, v := range deviceHosts { + deviceSvcHosts = append(deviceSvcHosts, fmt.Sprintf("%s=%s", k, v)) + } + + wgParams.PublicPeers = publicPeers + wgParams.DNS = klDevice.IPAddr + wgParams.ListenPort = 31820 + + dnsServerArgs := make([]string, 0, len(gvpnConns)) + for _, gvpnConn := range gvpnConns { + if gvpnConn.Spec.GlobalIP != "" { + dnsServerArgs = append(dnsServerArgs, fmt.Sprintf("%s=%s:53", gvpnConn.Spec.DNSSuffix, gvpnConn.Spec.GlobalIP)) + } + } + + resourceName := fmt.Sprintf("kloudlite-device-%s", gv.Name) + resourceNamespace := accNs + selector := map[string]string{ + "app": resourceName, + } + + // wgEndpoint := d.env.KloudliteGlobalVPNDeviceHost + + gao, err := d.accountsSvc.GetAccount(ctx, string(ctx.UserId), ctx.AccountName) + if err != nil { + return errors.NewE(err) + } + + gwRegion, ok := d.env.AvailableKloudliteRegions[gao.KloudliteGatewayRegion] + if !ok { + return errors.Newf("invalid gateway region %q", gao.KloudliteGatewayRegion) + } + + wgEndpoint := gwRegion.PublicDNSHost + + c, err := k8s.RestConfigFromKubeConfig([]byte(gwRegion.Kubeconfig)) + if err != nil { + return errors.NewE(err) + } + + yc, err := kubectl.NewYAMLClient(c, kubectl.YAMLClientOpts{}) + if err != nil { + return errors.NewE(err) + } + + service := &corev1.Service{} + + wgSvcName := fmt.Sprintf("%s-wg", resourceName) + + svcBytes, err := templates.ParseBytes(svcTemplate, templates.GatewayServiceTemplateVars{ + Name: wgSvcName, + Namespace: resourceNamespace, + WireguardPort: wgParams.ListenPort, + Selector: selector, + }) + if err != nil { + return errors.NewE(err) + } + + ctx2, cf := func() (context.Context, context.CancelFunc) { + if d.env.IsDev { + return context.WithCancel(ctx) + } + return context.WithTimeout(ctx, 5*time.Second) + }() + defer cf() + + for { + if ctx2.Err() != nil { + return ctx2.Err() + } + service, err = yc.Client().CoreV1().Services(resourceNamespace).Get(ctx, wgSvcName, metav1.GetOptions{}) + if err != nil { + if !apiErrors.IsNotFound(err) { + return err + } + if _, err := yc.ApplyYAML(ctx, svcBytes); err != nil { + return errors.NewE(err) + } + continue + } + + if service.Spec.Ports[0].NodePort != 0 { + wgEndpoint = fmt.Sprintf("%s:%d", wgEndpoint, service.Spec.Ports[0].NodePort) + break + } + } + + if _, err := d.gvpnDevicesRepo.PatchById(ctx, klDevice.Id, repos.Document{ + fc.GlobalVPNDevicePublicEndpoint: wgEndpoint, + }); err != nil { + return err + } + + wgConfig, err := wgutils.GenerateWireguardConfig(*wgParams) + if err != nil { + return err + } + + deploymentBytes, err := templates.ParseBytes(b, templates.GVPNKloudliteDeviceTemplateVars{ + Name: resourceName, + Namespace: accNs, + WgConfig: wgConfig, + EnableKubeReverseProxy: false, + KubeReverseProxyImage: d.env.GlobalVPNKubeReverseProxyImage, + AuthzToken: d.env.GlobalVPNKubeReverseProxyAuthzToken, + GatewayDNSServers: strings.Join(dnsServerArgs, ","), + GatewayServiceHosts: strings.Join(deviceSvcHosts, ","), + WireguardPort: wgParams.ListenPort, + + KloudliteAccount: gv.AccountName, + }) + if err != nil { + return err + } + + d.logger.Info("applying yaml", "yaml", string(deploymentBytes)) + if _, err := yc.ApplyYAML(ctx, deploymentBytes); err != nil { + return errors.NewE(err) + } + + return nil +} + +func (d *domain) syncKloudliteGatewayDevice2(ctx InfraContext, gvpnName string) error { + t := time.Now() + defer func() { + d.logger.Info("syncKloudliteGatewayDevice2", "took", time.Since(t).Seconds()) }() // 1. parse deployment template b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) @@ -454,8 +638,6 @@ func (d *domain) syncKloudliteGatewayDevice(ctx InfraContext, gvpnName string) e "app": resourceName, } - // wgEndpoint := d.env.KloudliteGlobalVPNDeviceHost - gao, err := d.accountsSvc.GetAccount(ctx, string(ctx.UserId), ctx.AccountName) if err != nil { return errors.NewE(err) @@ -574,10 +756,12 @@ func (d *domain) syncKloudliteDeviceOnPlatform(ctx InfraContext, gvpnName string return errors.NewE(err) } - accNs, err := d.getAccNamespace(ctx) - if err != nil { - return errors.NewE(err) - } + accNs := fmt.Sprintf("kl-%s", ctx.AccountName) + + // accNs, err := d.getAccNamespace(ctx) + // if err != nil { + // return errors.NewE(err) + // } gv, err := d.findGlobalVPN(ctx, gvpnName) if err != nil { @@ -639,7 +823,12 @@ func (d *domain) syncKloudliteDeviceOnPlatform(ctx InfraContext, gvpnName string } service := &corev1.Service{} - ctx2, cf := context.WithTimeout(ctx, 5*time.Second) + ctx2, cf := func() (context.Context, context.CancelFunc) { + if d.env.IsDev { + return context.WithCancel(ctx) + } + return context.WithTimeout(ctx, 5*time.Second) + }() defer cf() wgEndpoint := d.env.KloudliteGlobalVPNDeviceHost @@ -792,7 +981,7 @@ func (d *domain) applyHelmKloudliteAgent(ctx InfraContext, clusterToken string, return errors.NewE(err) } - if err := d.resDispatcher.ApplyToTargetCluster(ctx, cluster.Name, &uhr.HelmChart, uhr.RecordVersion); err != nil { + if err := d.resDispatcher.ApplyToTargetCluster(ctx, &entities.DispatchAddr{AccountName: ctx.AccountName, ClusterName: cluster.Name}, &uhr.HelmChart, uhr.RecordVersion); err != nil { return errors.NewE(err) } @@ -800,7 +989,7 @@ func (d *domain) applyHelmKloudliteAgent(ctx InfraContext, clusterToken string, } func (d *domain) UpgradeHelmKloudliteAgent(ctx InfraContext, clusterName string) error { - out, err := d.messageOfficeInternalClient.GetClusterToken(ctx, &message_office_internal.GetClusterTokenIn{ + out, err := d.moSvc.GetClusterToken(ctx, &ports.GetClusterTokenIn{ AccountName: ctx.AccountName, ClusterName: clusterName, }) diff --git a/apps/infra/internal/domain/domain.go b/apps/infra/internal/domain/domain.go index 7129e3a82..ee6393fc6 100644 --- a/apps/infra/internal/domain/domain.go +++ b/apps/infra/internal/domain/domain.go @@ -3,6 +3,7 @@ package domain import ( "fmt" "io" + "log/slog" "os" "strconv" @@ -13,14 +14,14 @@ import ( "github.com/kloudlite/api/pkg/errors" "github.com/kloudlite/api/pkg/k8s" + "github.com/kloudlite/api/apps/infra/internal/domain/ports" "github.com/kloudlite/api/apps/infra/internal/entities" "github.com/kloudlite/api/apps/infra/internal/env" constant "github.com/kloudlite/api/constants" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" - message_office_internal "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/message-office-internal" + fn "github.com/kloudlite/api/pkg/functions" - "github.com/kloudlite/api/pkg/logging" "github.com/kloudlite/api/pkg/repos" "github.com/kloudlite/operator/pkg/constants" "go.uber.org/fx" @@ -30,7 +31,7 @@ import ( ) type domain struct { - logger logging.Logger + logger *slog.Logger env *env.Env clusterRepo repos.DbRepo[*entities.Cluster] @@ -56,24 +57,24 @@ type domain struct { pvRepo repos.DbRepo[*entities.PersistentVolume] volumeAttachmentRepo repos.DbRepo[*entities.VolumeAttachment] - iamClient iam.IAMClient - consoleClient console.ConsoleClient - accountsSvc AccountsSvc - messageOfficeInternalClient message_office_internal.MessageOfficeInternalClient - resDispatcher ResourceDispatcher - k8sClient k8s.Client - resourceEventPublisher ResourceEventPublisher + iamClient iam.IAMClient + consoleClient console.ConsoleClient + accountsSvc AccountsSvc + moSvc ports.MessageOfficeService + resDispatcher ResourceDispatcher + k8sClient k8s.Client + resourceEventPublisher ResourceEventPublisher msvcTemplates []*entities.MsvcTemplate msvcTemplatesMap map[string]map[string]*entities.MsvcTemplateEntry } -func (d *domain) resyncToTargetCluster(ctx InfraContext, action types.SyncAction, clusterName string, obj client.Object, recordVersion int) error { +func (d *domain) resyncToTargetCluster(ctx InfraContext, action types.SyncAction, dispatchAddr *entities.DispatchAddr, obj client.Object, recordVersion int) error { switch action { case types.SyncActionApply: - return d.resDispatcher.ApplyToTargetCluster(ctx, clusterName, obj, recordVersion) + return d.resDispatcher.ApplyToTargetCluster(ctx, dispatchAddr, obj, recordVersion) case types.SyncActionDelete: - return d.resDispatcher.DeleteFromTargetCluster(ctx, clusterName, obj) + return d.resDispatcher.DeleteFromTargetCluster(ctx, dispatchAddr, obj) } return errors.Newf("unknonw action: %q", action) } @@ -87,7 +88,7 @@ func addTrackingId(obj client.Object, id repos.ID) { labels := obj.GetLabels() if labels == nil { - labels = make(map[string]string, 1) + labels = make(map[string]string, 2) } labels[constant.ObservabilityTrackingKey] = string(id) obj.SetLabels(labels) @@ -198,8 +199,8 @@ var Module = fx.Module("domain", iamClient iam.IAMClient, consoleClient console.ConsoleClient, accountsSvc AccountsSvc, - msgOfficeInternalClient message_office_internal.MessageOfficeInternalClient, - logger logging.Logger, + moSvc ports.MessageOfficeService, + logger *slog.Logger, resourceEventPublisher ResourceEventPublisher, ) (Domain, error) { open, err := os.Open(env.MsvcTemplateFilePath) @@ -246,19 +247,19 @@ var Module = fx.Module("domain", gvpnRepo: gvpnRepo, gvpnDevicesRepo: gvpnDevicesRepo, - byokClusterRepo: byokClusterRepo, - nodeRepo: nodeRepo, - nodePoolRepo: nodePoolRepo, - secretRepo: secretRepo, - domainEntryRepo: domainNameRepo, - resDispatcher: resourceDispatcher, - k8sClient: k8sClient, - iamClient: iamClient, - consoleClient: consoleClient, - accountsSvc: accountsSvc, - messageOfficeInternalClient: msgOfficeInternalClient, - resourceEventPublisher: resourceEventPublisher, - helmReleaseRepo: helmReleaseRepo, + byokClusterRepo: byokClusterRepo, + nodeRepo: nodeRepo, + nodePoolRepo: nodePoolRepo, + secretRepo: secretRepo, + domainEntryRepo: domainNameRepo, + resDispatcher: resourceDispatcher, + k8sClient: k8sClient, + iamClient: iamClient, + consoleClient: consoleClient, + accountsSvc: accountsSvc, + moSvc: moSvc, + resourceEventPublisher: resourceEventPublisher, + helmReleaseRepo: helmReleaseRepo, pvcRepo: pvcRepo, volumeAttachmentRepo: volumeAttachmentRepo, diff --git a/apps/infra/internal/domain/global-vpn-cluster-connection.go b/apps/infra/internal/domain/global-vpn-cluster-connection.go index 3c43d6105..6b3a4935c 100644 --- a/apps/infra/internal/domain/global-vpn-cluster-connection.go +++ b/apps/infra/internal/domain/global-vpn-cluster-connection.go @@ -66,7 +66,7 @@ func (d *domain) getGlobalVPNConnectionPeers(args getGlobalVPNConnectionPeersArg if c.Visibility.Mode != entities.ClusterVisibilityModePrivate { if c.Spec.LoadBalancer == nil { - d.logger.Infof("loadbalancer not available for gvpn %s", c.Name) + d.logger.Info("loadbalancer not available", "gvpn", c.Name) continue } @@ -228,6 +228,7 @@ func (d *domain) claimNextClusterCIDR(ctx InfraContext, clusterName string, gvpn // FIXME: handle gracefully continue } + if _, err := d.gvpnRepo.PatchById(ctx, gvpn.Id, repos.Document{"$inc": map[string]any{fc.GlobalVPNNumAllocatedClusterCIDRs: 1}}); err != nil { continue } @@ -255,7 +256,7 @@ func (d *domain) claimNextClusterCIDR(ctx InfraContext, clusterName string, gvpn ClusterSvcCIDR: cidr, ClaimedByCluster: clusterName, }); err != nil { - d.logger.Warnf("cluster svc CIDR %s, already claimed, trying another", cidr) + d.logger.Warn("cluster svc CIDR, already claimed, trying another", "CIDR", cidr) if cidrFilter == nil { cidrFilter = &repos.MatchFilter{} } @@ -281,9 +282,12 @@ func (d *domain) createGlobalVPNConnection(ctx InfraContext, gvpnConn entities.G return nil, err } - // if gvpnConn.Spec.WgInterface == nil { - // gvpnConn.Spec.WgInterface = &gvpn.WgInterface - // } + if gvpnConn.DispatchAddr == nil { + gvpnConn.DispatchAddr = &entities.DispatchAddr{ + AccountName: ctx.AccountName, + ClusterName: gvpnConn.ClusterName, + } + } gvpnConn.SyncStatus = t.GenSyncStatus(t.SyncActionApply, 0) @@ -385,7 +389,11 @@ func (d *domain) deleteGlobalVPNConnection(ctx InfraContext, clusterName string, return nil } -func (d *domain) ensureGlobalVPNConnection(ctx InfraContext, clusterName string, groupName string) (*entities.GlobalVPNConnection, error) { +func (d *domain) EnsureGlobalVPNConnection(ctx InfraContext, clusterName string, groupName string, dispatchAddr *entities.DispatchAddr) (*entities.GlobalVPNConnection, error) { + return d.ensureGlobalVPNConnection(ctx, clusterName, groupName, dispatchAddr) +} + +func (d *domain) ensureGlobalVPNConnection(ctx InfraContext, clusterName string, groupName string, dispatchAddr *entities.DispatchAddr) (*entities.GlobalVPNConnection, error) { gvpnConn, err := d.gvpnConnRepo.FindOne(ctx, repos.Filter{ fields.AccountName: ctx.AccountName, fields.ClusterName: clusterName, @@ -402,7 +410,11 @@ func (d *domain) ensureGlobalVPNConnection(ctx InfraContext, clusterName string, return gvpnConn, nil } - gvpnGateway := networkingv1.Gateway{ObjectMeta: metav1.ObjectMeta{Name: groupName}} + gvpnGateway := networkingv1.Gateway{ObjectMeta: metav1.ObjectMeta{ + Name: groupName, + // Name: fmt.Sprintf("%s-%s", ctx.AccountName, groupName), + // Name: fmt.Sprintf("%s-%s", ctx.AccountName, groupName), + }} gvpnGateway.EnsureGVK() return d.createGlobalVPNConnection(ctx, entities.GlobalVPNConnection{ @@ -411,12 +423,13 @@ func (d *domain) ensureGlobalVPNConnection(ctx InfraContext, clusterName string, ResourceMetadata: common.ResourceMetadata{DisplayName: groupName, CreatedBy: common.CreatedOrUpdatedByKloudlite, LastUpdatedBy: common.CreatedOrUpdatedByKloudlite}, AccountName: ctx.AccountName, ClusterName: clusterName, + DispatchAddr: dispatchAddr, ParsedWgParams: nil, }) } func (d *domain) applyGlobalVPNConnection(ctx InfraContext, gvpn *entities.GlobalVPNConnection) error { - return d.resDispatcher.ApplyToTargetCluster(ctx, gvpn.ClusterName, &gvpn.Gateway, gvpn.RecordVersion) + return d.resDispatcher.ApplyToTargetCluster(ctx, gvpn.DispatchAddr, &gvpn.Gateway, gvpn.RecordVersion) } func (d *domain) findGlobalVPNConnection(ctx InfraContext, clusterName string, groupName string) (*entities.GlobalVPNConnection, error) { @@ -462,25 +475,34 @@ func (d *domain) OnGlobalVPNConnectionDeleteMessage(ctx InfraContext, clusterNam return err } -func (d *domain) OnGlobalVPNConnectionUpdateMessage(ctx InfraContext, clusterName string, gvpn entities.GlobalVPNConnection, status types.ResourceStatus, opts UpdateAndDeleteOpts) error { - xconn, err := d.findGlobalVPNConnection(ctx, clusterName, gvpn.Name) +func (d *domain) OnGlobalVPNConnectionUpdateMessage(ctx InfraContext, dispatchAddr entities.DispatchAddr, gvpn entities.GlobalVPNConnection, status types.ResourceStatus, opts UpdateAndDeleteOpts) error { + // FIXME: need a way to find global vpn connection, receiving it from other clusters + + xconn, err := d.gvpnConnRepo.FindOne(ctx, repos.Filter{ + fields.AccountName: ctx.AccountName, + fc.GlobalVPNConnectionDispatchAddrAccountName: dispatchAddr.AccountName, + fc.GlobalVPNConnectionDispatchAddrClusterName: dispatchAddr.ClusterName, + }) if err != nil { return errors.NewE(err) } + if xconn == nil { + return errors.ErrNotFound{Message: "global vpn connection not found"} + } // INFO: BYOK cluster does not have any status update message - if d.isBYOKCluster(ctx, xconn.ClusterName) { - if _, err := d.byokClusterRepo.PatchOne(ctx, entities.UniqueBYOKClusterFilter(ctx.AccountName, clusterName), repos.Document{ - fc.SyncStatusState: t.SyncStateUpdatedAtAgent, - fc.SyncStatusLastSyncedAt: opts.MessageTimestamp, - fc.SyncStatusError: nil, - }); err != nil { - return errors.NewE(err) - } - } + // if d.isBYOKCluster(ctx, xconn.ClusterName) { + // if _, err := d.byokClusterRepo.PatchOne(ctx, entities.UniqueBYOKClusterFilter(ctx.AccountName, clusterName), repos.Document{ + // fc.SyncStatusState: t.SyncStateUpdatedAtAgent, + // fc.SyncStatusLastSyncedAt: opts.MessageTimestamp, + // fc.SyncStatusError: nil, + // }); err != nil { + // return errors.NewE(err) + // } + // } if _, err := d.matchRecordVersion(gvpn.Annotations, xconn.RecordVersion); err != nil { - return d.resyncToTargetCluster(ctx, xconn.SyncStatus.Action, clusterName, &xconn.Gateway, xconn.RecordVersion) + return d.resyncToTargetCluster(ctx, xconn.SyncStatus.Action, xconn.DispatchAddr, &xconn.Gateway, xconn.RecordVersion) } recordVersion, err := d.matchRecordVersion(gvpn.Annotations, xconn.RecordVersion) @@ -494,7 +516,7 @@ func (d *domain) OnGlobalVPNConnectionUpdateMessage(ctx InfraContext, clusterNam if gvpn.ParsedWgParams != nil { patchDoc[fc.GlobalVPNConnectionParsedWgParams] = gvpn.ParsedWgParams - patchDoc[fc.GlobalVPNConnectionSpecAdminNamespace] = gvpn.Spec.AdminNamespace + patchDoc[fc.GlobalVPNConnectionSpecTargetNamespace] = gvpn.Spec.TargetNamespace patchDoc[fc.GlobalVPNConnectionSpecLoadBalancer] = gvpn.Spec.LoadBalancer patchDoc[fc.GlobalVPNConnectionSpecWireguardKeysRef] = gvpn.Spec.WireguardKeysRef } @@ -516,7 +538,7 @@ func (d *domain) OnGlobalVPNConnectionUpdateMessage(ctx InfraContext, clusterNam return errors.NewE(err) } - d.resourceEventPublisher.PublishResourceEvent(ctx, clusterName, ResourceTypeClusterConnection, ugvpn.Name, PublishUpdate) + d.resourceEventPublisher.PublishResourceEvent(ctx, dispatchAddr.ClusterName, ResourceTypeClusterConnection, ugvpn.Name, PublishUpdate) return nil } diff --git a/apps/infra/internal/domain/global-vpn-devices.go b/apps/infra/internal/domain/global-vpn-devices.go index a9e34a8a1..003ae7463 100644 --- a/apps/infra/internal/domain/global-vpn-devices.go +++ b/apps/infra/internal/domain/global-vpn-devices.go @@ -87,7 +87,7 @@ func (d *domain) claimNextFreeDeviceIP(ctx InfraContext, deviceName string, gvpn ipAddrFilter.MatchType = repos.MatchTypeNotInArray ipAddrFilter.NotInArray = append(ipAddrFilter.NotInArray, ipAddr) - d.logger.Warnf("ip addr already claimed (err: %s), retrying again", err.Error()) + d.logger.Warn("ip addr already claimed, will retry again, got", "err", err) <-time.After(50 * time.Millisecond) continue } diff --git a/apps/infra/internal/domain/global-vpn.go b/apps/infra/internal/domain/global-vpn.go index d5b9e0b8b..4918f4cf9 100644 --- a/apps/infra/internal/domain/global-vpn.go +++ b/apps/infra/internal/domain/global-vpn.go @@ -203,7 +203,7 @@ func (d *domain) findGlobalVPN(ctx InfraContext, gvpnName string) (*entities.Glo } if cg == nil { - return nil, ErrClusterNotFound + return nil, errors.ErrNotFound{Message: fmt.Sprintf("no global vpn with name=%s", gvpnName)} } return cg, nil } diff --git a/apps/infra/internal/domain/helm-release.go b/apps/infra/internal/domain/helm-release.go index a47ddbfee..28cfea334 100644 --- a/apps/infra/internal/domain/helm-release.go +++ b/apps/infra/internal/domain/helm-release.go @@ -79,7 +79,7 @@ func (d *domain) GetHelmRelease(ctx InfraContext, clusterName string, hrName str func (d *domain) applyHelmRelease(ctx InfraContext, hr *entities.HelmRelease) error { addTrackingId(&hr.HelmChart, hr.Id) - return d.resDispatcher.ApplyToTargetCluster(ctx, hr.ClusterName, &hr.HelmChart, hr.RecordVersion) + return d.resDispatcher.ApplyToTargetCluster(ctx, hr.DispatchAddr, &hr.HelmChart, hr.RecordVersion) } func (d *domain) CreateHelmRelease(ctx InfraContext, clusterName string, hr entities.HelmRelease) (*entities.HelmRelease, error) { @@ -91,6 +91,10 @@ func (d *domain) CreateHelmRelease(ctx InfraContext, clusterName string, hr enti return nil, errors.NewE(err) } + if hr.DispatchAddr == nil { + hr.DispatchAddr = &entities.DispatchAddr{AccountName: ctx.AccountName, ClusterName: clusterName} + } + hr.IncrementRecordVersion() hr.CreatedBy = common.CreatedOrUpdatedBy{ UserId: ctx.UserId, @@ -127,7 +131,7 @@ func (d *domain) CreateHelmRelease(ctx InfraContext, clusterName string, hr enti d.resourceEventPublisher.PublishResourceEvent(ctx, nhr.ClusterName, ResourceTypeHelmRelease, nhr.Name, PublishAdd) - if err = d.resDispatcher.ApplyToTargetCluster(ctx, clusterName, &corev1.Namespace{ + if err = d.resDispatcher.ApplyToTargetCluster(ctx, hr.DispatchAddr, &corev1.Namespace{ TypeMeta: metav1.TypeMeta{ Kind: "Namespace", APIVersion: "v1", @@ -206,7 +210,7 @@ func (d *domain) DeleteHelmRelease(ctx InfraContext, clusterName string, name st d.resourceEventPublisher.PublishResourceEvent(ctx, uphr.ClusterName, ResourceTypeHelmRelease, uphr.Name, PublishUpdate) - return d.resDispatcher.DeleteFromTargetCluster(ctx, clusterName, &uphr.HelmChart) + return d.resDispatcher.DeleteFromTargetCluster(ctx, uphr.DispatchAddr, &uphr.HelmChart) } func (d *domain) OnHelmReleaseApplyError(ctx InfraContext, clusterName string, name string, errMsg string, opts UpdateAndDeleteOpts) error { @@ -255,7 +259,7 @@ func (d *domain) OnHelmReleaseUpdateMessage(ctx InfraContext, clusterName string recordVersion, err := d.matchRecordVersion(hr.Annotations, xhr.RecordVersion) if err != nil { - return d.resyncToTargetCluster(ctx, xhr.SyncStatus.Action, clusterName, xhr, xhr.RecordVersion) + return d.resyncToTargetCluster(ctx, xhr.SyncStatus.Action, xhr.DispatchAddr, xhr, xhr.RecordVersion) } uphr, err := d.helmReleaseRepo.PatchById( diff --git a/apps/infra/internal/domain/nodepool.go b/apps/infra/internal/domain/nodepool.go index dc5020690..3f5671532 100644 --- a/apps/infra/internal/domain/nodepool.go +++ b/apps/infra/internal/domain/nodepool.go @@ -20,7 +20,7 @@ import ( func (d *domain) applyNodePool(ctx InfraContext, np *entities.NodePool) error { addTrackingId(&np.NodePool, np.Id) - return d.resDispatcher.ApplyToTargetCluster(ctx, np.ClusterName, &np.NodePool, np.RecordVersion) + return d.resDispatcher.ApplyToTargetCluster(ctx, np.DispatchAddr, &np.NodePool, np.RecordVersion) } func (d *domain) CreateNodePool(ctx InfraContext, clusterName string, nodepool entities.NodePool) (*entities.NodePool, error) { @@ -28,6 +28,10 @@ func (d *domain) CreateNodePool(ctx InfraContext, clusterName string, nodepool e return nil, errors.NewE(err) } + if nodepool.DispatchAddr == nil { + nodepool.DispatchAddr = &entities.DispatchAddr{AccountName: ctx.AccountName, ClusterName: clusterName} + } + nodepool.IncrementRecordVersion() nodepool.CreatedBy = common.CreatedOrUpdatedBy{ UserId: ctx.UserId, @@ -98,7 +102,7 @@ func (d *domain) CreateNodePool(ctx InfraContext, clusterName string, nodepool e // INFO: because kube-system is omnipresent on k8s k8sSecret.Namespace = "kube-system" - if err := d.resDispatcher.ApplyToTargetCluster(ctx, clusterName, k8sSecret, nodepool.RecordVersion); err != nil { + if err := d.resDispatcher.ApplyToTargetCluster(ctx, nodepool.DispatchAddr, k8sSecret, nodepool.RecordVersion); err != nil { return nil, errors.NewE(err) } @@ -222,7 +226,7 @@ func (d *domain) DeleteNodePool(ctx InfraContext, clusterName string, poolName s } d.resourceEventPublisher.PublishResourceEvent(ctx, clusterName, ResourceTypeNodePool, unp.Name, PublishUpdate) - return d.resDispatcher.DeleteFromTargetCluster(ctx, clusterName, &unp.NodePool) + return d.resDispatcher.DeleteFromTargetCluster(ctx, unp.DispatchAddr, &unp.NodePool) } func (d *domain) GetNodePool(ctx InfraContext, clusterName string, poolName string) (*entities.NodePool, error) { @@ -276,7 +280,7 @@ func (d *domain) ResyncNodePool(ctx InfraContext, clusterName string, poolName s return errors.NewE(err) } - return d.resyncToTargetCluster(ctx, np.SyncStatus.Action, clusterName, &np.NodePool, np.RecordVersion) + return d.resyncToTargetCluster(ctx, np.SyncStatus.Action, np.DispatchAddr, &np.NodePool, np.RecordVersion) } // on message events @@ -308,7 +312,7 @@ func (d *domain) OnNodePoolUpdateMessage(ctx InfraContext, clusterName string, n } if _, err := d.matchRecordVersion(nodePool.Annotations, xnp.RecordVersion); err != nil { - return d.resyncToTargetCluster(ctx, xnp.SyncStatus.Action, clusterName, &xnp.NodePool, xnp.RecordVersion) + return d.resyncToTargetCluster(ctx, xnp.SyncStatus.Action, xnp.DispatchAddr, &xnp.NodePool, xnp.RecordVersion) } recordVersion, err := d.matchRecordVersion(nodePool.Annotations, xnp.RecordVersion) diff --git a/apps/infra/internal/domain/ports.go b/apps/infra/internal/domain/ports.go index bde574f7e..ffd166620 100644 --- a/apps/infra/internal/domain/ports.go +++ b/apps/infra/internal/domain/ports.go @@ -2,6 +2,8 @@ package domain import ( "context" + + "github.com/kloudlite/api/apps/infra/internal/entities" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/accounts" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -11,8 +13,8 @@ type AccountsSvc interface { } type ResourceDispatcher interface { - ApplyToTargetCluster(ctx InfraContext, clusterName string, obj client.Object, recordVersion int) error - DeleteFromTargetCluster(ctx InfraContext, clusterName string, obj client.Object) error + ApplyToTargetCluster(ctx InfraContext, dispatchAddr *entities.DispatchAddr, obj client.Object, recordVersion int) error + DeleteFromTargetCluster(ctx InfraContext, dispatchAddr *entities.DispatchAddr, obj client.Object) error } type PublishMsg string diff --git a/apps/infra/internal/domain/ports/message-office-svc.go b/apps/infra/internal/domain/ports/message-office-svc.go new file mode 100644 index 000000000..71a137e33 --- /dev/null +++ b/apps/infra/internal/domain/ports/message-office-svc.go @@ -0,0 +1,38 @@ +package ports + +import "context" + +type MessageOfficeService interface { + GetAllocatedPlatformEdgeCluster(ctx context.Context, args *GetAllocatedPlatformEdgeClusterIn) (*GetAllocatedPlatformEdgeClusterOut, error) + + GetClusterToken(ctx context.Context, args *GetClusterTokenIn) (*GetClusterTokenOut, error) + + GenerateClusterToken(ctx context.Context, args *GenerateClusterTokenIn) (*GenerateClusterTokenOut, error) +} + +type GetAllocatedPlatformEdgeClusterIn struct { + AccountName string + ClusterName string +} + +type GetAllocatedPlatformEdgeClusterOut struct { + PublicDNSHost string +} + +type GetClusterTokenIn struct { + AccountName string + ClusterName string +} + +type GetClusterTokenOut struct { + ClusterToken string +} + +type GenerateClusterTokenIn struct { + AccountName string + ClusterName string +} + +type GenerateClusterTokenOut struct{ + ClusterToken string +} diff --git a/apps/infra/internal/domain/pv.go b/apps/infra/internal/domain/pv.go index b01e438bf..145115afc 100644 --- a/apps/infra/internal/domain/pv.go +++ b/apps/infra/internal/domain/pv.go @@ -57,7 +57,7 @@ func (d *domain) DeletePV(ctx InfraContext, clusterName string, pvName string) e } d.resourceEventPublisher.PublishResourceEvent(ctx, clusterName, ResourceTypeNodePool, upv.Name, PublishUpdate) - return d.resDispatcher.DeleteFromTargetCluster(ctx, clusterName, &upv.PersistentVolume) + return d.resDispatcher.DeleteFromTargetCluster(ctx, &entities.DispatchAddr{AccountName: ctx.AccountName, ClusterName: clusterName}, &upv.PersistentVolume) } // OnPVDeleteMessage implements Domain. diff --git a/apps/infra/internal/domain/templates/types.go b/apps/infra/internal/domain/templates/types.go index 0bb89f946..49dc16fa5 100644 --- a/apps/infra/internal/domain/templates/types.go +++ b/apps/infra/internal/domain/templates/types.go @@ -6,19 +6,19 @@ type GVPNKloudliteDeviceTemplateVars struct { WgConfig string WireguardPort uint16 - KloudliteAccount string + KloudliteAccount string - EnableKubeReverseProxy bool - KubeReverseProxyImage string - AuthzToken string + EnableKubeReverseProxy bool + KubeReverseProxyImage string + AuthzToken string GatewayDNSServers string GatewayServiceHosts string } type GatewayServiceTemplateVars struct { - Name string - Namespace string - WireguardPort uint16 - Selector map[string]string + Name string + Namespace string + WireguardPort uint16 + Selector map[string]string } diff --git a/apps/infra/internal/entities/field-constants/generated_constants.go b/apps/infra/internal/entities/field-constants/generated_constants.go index a4986510c..eccdabad3 100644 --- a/apps/infra/internal/entities/field-constants/generated_constants.go +++ b/apps/infra/internal/entities/field-constants/generated_constants.go @@ -157,6 +157,9 @@ const ( ClusterVisbilityPublicEndpoint = "publicEndpoint" ) +// constant vars generated for struct DispatchAddr +const () + // constant vars generated for struct DomainEntry const ( DomainEntryDomainName = "domainName" @@ -204,32 +207,34 @@ const ( // constant vars generated for struct GlobalVPNConnection const ( - GlobalVPNConnectionClusterSvcCIDR = "clusterSvcCIDR" - GlobalVPNConnectionDeviceRef = "deviceRef" - GlobalVPNConnectionDeviceRefIpAddr = "deviceRef.ipAddr" - GlobalVPNConnectionDeviceRefName = "deviceRef.name" - GlobalVPNConnectionGlobalVPNName = "globalVPNName" - GlobalVPNConnectionParsedWgParams = "parsedWgParams" - GlobalVPNConnectionParsedWgParamsPrivateKey = "parsedWgParams.private_key" - GlobalVPNConnectionParsedWgParamsPublicKey = "parsedWgParams.public_key" - GlobalVPNConnectionSpec = "spec" - GlobalVPNConnectionSpecAdminNamespace = "spec.adminNamespace" - GlobalVPNConnectionSpecClusterCIDR = "spec.clusterCIDR" - GlobalVPNConnectionSpecDnsSuffix = "spec.dnsSuffix" - GlobalVPNConnectionSpecGlobalIP = "spec.globalIP" - GlobalVPNConnectionSpecLoadBalancer = "spec.loadBalancer" - GlobalVPNConnectionSpecLoadBalancerHosts = "spec.loadBalancer.hosts" - GlobalVPNConnectionSpecLoadBalancerPort = "spec.loadBalancer.port" - GlobalVPNConnectionSpecNodePort = "spec.nodePort" - GlobalVPNConnectionSpecPeers = "spec.peers" - GlobalVPNConnectionSpecServiceType = "spec.serviceType" - GlobalVPNConnectionSpecSvcCIDR = "spec.svcCIDR" - GlobalVPNConnectionSpecWireguardKeysRef = "spec.wireguardKeysRef" - GlobalVPNConnectionSpecWireguardKeysRefName = "spec.wireguardKeysRef.name" - GlobalVPNConnectionSpecWireguardKeysRefNamespace = "spec.wireguardKeysRef.namespace" - GlobalVPNConnectionVisibility = "visibility" - GlobalVPNConnectionVisibilityMode = "visibility.mode" - GlobalVPNConnectionVisibilityPublicEndpoint = "visibility.publicEndpoint" + GlobalVPNConnectionClusterSvcCIDR = "clusterSvcCIDR" + GlobalVPNConnectionDeviceRef = "deviceRef" + GlobalVPNConnectionDeviceRefIpAddr = "deviceRef.ipAddr" + GlobalVPNConnectionDeviceRefName = "deviceRef.name" + GlobalVPNConnectionDispatchAddr = "dispatchAddr" + GlobalVPNConnectionDispatchAddrAccountName = "dispatchAddr.accountName" + GlobalVPNConnectionDispatchAddrClusterName = "dispatchAddr.clusterName" + GlobalVPNConnectionGlobalVPNName = "globalVPNName" + GlobalVPNConnectionParsedWgParams = "parsedWgParams" + GlobalVPNConnectionParsedWgParamsPrivateKey = "parsedWgParams.private_key" + GlobalVPNConnectionParsedWgParamsPublicKey = "parsedWgParams.public_key" + GlobalVPNConnectionSpec = "spec" + GlobalVPNConnectionSpecClusterCIDR = "spec.clusterCIDR" + GlobalVPNConnectionSpecDnsSuffix = "spec.dnsSuffix" + GlobalVPNConnectionSpecGlobalIP = "spec.globalIP" + GlobalVPNConnectionSpecLoadBalancer = "spec.loadBalancer" + GlobalVPNConnectionSpecLoadBalancerHosts = "spec.loadBalancer.hosts" + GlobalVPNConnectionSpecLoadBalancerPort = "spec.loadBalancer.port" + GlobalVPNConnectionSpecNodePort = "spec.nodePort" + GlobalVPNConnectionSpecPeers = "spec.peers" + GlobalVPNConnectionSpecServiceType = "spec.serviceType" + GlobalVPNConnectionSpecSvcCIDR = "spec.svcCIDR" + GlobalVPNConnectionSpecTargetNamespace = "spec.targetNamespace" + GlobalVPNConnectionSpecWireguardKeysRef = "spec.wireguardKeysRef" + GlobalVPNConnectionSpecWireguardKeysRefName = "spec.wireguardKeysRef.name" + GlobalVPNConnectionVisibility = "visibility" + GlobalVPNConnectionVisibilityMode = "visibility.mode" + GlobalVPNConnectionVisibilityPublicEndpoint = "visibility.publicEndpoint" ) // constant vars generated for struct GlobalVPNDevice @@ -244,6 +249,9 @@ const ( // constant vars generated for struct HelmRelease const ( + HelmReleaseDispatchAddr = "dispatchAddr" + HelmReleaseDispatchAddrAccountName = "dispatchAddr.accountName" + HelmReleaseDispatchAddrClusterName = "dispatchAddr.clusterName" HelmReleaseSpec = "spec" HelmReleaseSpecChartName = "spec.chartName" HelmReleaseSpecChartRepoURL = "spec.chartRepoURL" @@ -324,6 +332,9 @@ const ( // constant vars generated for struct NodePool const ( + NodePoolDispatchAddr = "dispatchAddr" + NodePoolDispatchAddrAccountName = "dispatchAddr.accountName" + NodePoolDispatchAddrClusterName = "dispatchAddr.clusterName" NodePoolSpec = "spec" NodePoolSpecAllowSSH = "spec.allowSSH" NodePoolSpecAws = "spec.aws" diff --git a/apps/infra/internal/entities/global-vpn-connection.go b/apps/infra/internal/entities/global-vpn-connection.go index 6c9137ead..7da525c56 100644 --- a/apps/infra/internal/entities/global-vpn-connection.go +++ b/apps/infra/internal/entities/global-vpn-connection.go @@ -15,6 +15,11 @@ type GlobalVPNConnDeviceRef struct { IPAddr string `json:"ipAddr"` } +type DispatchAddr struct { + AccountName string `json:"accountName"` + ClusterName string `json:"clusterName"` +} + type WgParams struct { WgPrivateKey string `json:"wg_private_key"` WgPublicKey string `json:"wg_public_key"` @@ -48,6 +53,9 @@ type GlobalVPNConnection struct { // ClusterPublicEndpoint string `json:"clusterPublicEndpoint" graphql:"noinput"` DeviceRef GlobalVPNConnDeviceRef `json:"deviceRef" graphql:"noinput"` + // DispatchAddr is useful when globalvpn connection belongs to one account, but is deployed to another account + DispatchAddr *DispatchAddr `json:"dispatchAddr" graphql:"noinput"` + // ParsedWgParams *wgv1.WgParams `json:"parsedWgParams" graphql:"ignore"` ParsedWgParams *networkingv1.WireguardKeys `json:"parsedWgParams" graphql:"ignore"` SyncStatus t.SyncStatus `json:"syncStatus" graphql:"noinput"` @@ -70,9 +78,19 @@ var GlobalVPNConnectionIndices = []repos.IndexField{ }, { Field: []repos.IndexKey{ - {Key: "metadata.name", Value: repos.IndexAsc}, - {Key: "accountName", Value: repos.IndexAsc}, - {Key: "clusterName", Value: repos.IndexAsc}, + {Key: fc.MetadataName, Value: repos.IndexAsc}, + {Key: fc.AccountName, Value: repos.IndexAsc}, + {Key: fc.ClusterName, Value: repos.IndexAsc}, + }, + Unique: true, + }, + + { + Field: []repos.IndexKey{ + {Key: fc.GlobalVPNConnectionDispatchAddrAccountName, Value: repos.IndexAsc}, + {Key: fc.GlobalVPNConnectionDispatchAddrClusterName, Value: repos.IndexAsc}, + {Key: fc.MetadataName, Value: repos.IndexAsc}, + {Key: fc.AccountName, Value: repos.IndexAsc}, }, Unique: true, }, diff --git a/apps/infra/internal/entities/helm-release.go b/apps/infra/internal/entities/helm-release.go index 3ecf052bf..5cf314fa3 100644 --- a/apps/infra/internal/entities/helm-release.go +++ b/apps/infra/internal/entities/helm-release.go @@ -17,6 +17,8 @@ type HelmRelease struct { AccountName string `json:"accountName" graphql:"noinput"` ClusterName string `json:"clusterName" graphql:"noinput"` + DispatchAddr *DispatchAddr `json:"dispatchAddr" graphql:"noinput"` + SyncStatus t.SyncStatus `json:"syncStatus" graphql:"noinput"` } diff --git a/apps/infra/internal/entities/nodepool.go b/apps/infra/internal/entities/nodepool.go index aab9c8100..efc1760db 100644 --- a/apps/infra/internal/entities/nodepool.go +++ b/apps/infra/internal/entities/nodepool.go @@ -17,6 +17,8 @@ type NodePool struct { AccountName string `json:"accountName" graphql:"noinput"` ClusterName string `json:"clusterName" graphql:"noinput"` + DispatchAddr *DispatchAddr `json:"dispatchAddr" graphql:"noinput"` + SyncStatus t.SyncStatus `json:"syncStatus" graphql:"noinput"` } diff --git a/apps/infra/internal/framework/framework.go b/apps/infra/internal/framework/framework.go index 38ca29653..75c091eaa 100644 --- a/apps/infra/internal/framework/framework.go +++ b/apps/infra/internal/framework/framework.go @@ -6,6 +6,7 @@ import ( "log/slog" "github.com/kloudlite/api/apps/infra/internal/app" + "github.com/kloudlite/api/apps/infra/internal/app/adapters" "github.com/kloudlite/api/apps/infra/internal/env" "github.com/kloudlite/api/common" "github.com/kloudlite/api/pkg/errors" @@ -68,7 +69,7 @@ var Module = fx.Module("framework", return grpc.NewGrpcClient(ev.AccountsGrpcAddr) }), - fx.Provide(func(ev *env.Env) (app.MessageOfficeInternalGrpcClient, error) { + fx.Provide(func(ev *env.Env) (adapters.MesasageOfficeGRPCClient, error) { return grpc.NewGrpcClient(ev.MessageOfficeInternalGrpcAddr) }), diff --git a/apps/infra/main.go b/apps/infra/main.go index 8f870c166..d91ef0bd0 100644 --- a/apps/infra/main.go +++ b/apps/infra/main.go @@ -3,7 +3,6 @@ package main import ( "context" "flag" - "log/slog" "os" "time" @@ -25,6 +24,9 @@ import ( ) func main() { + start := time.Now() + common.PrintBuildInfo() + var isDev bool flag.BoolVar(&isDev, "dev", false, "--dev") @@ -33,25 +35,20 @@ func main() { flag.Parse() - logger, err := logging.New(&logging.Options{Name: "infra", Dev: isDev}) - if err != nil { - panic(err) + if isDev { + debug = true } + logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug, SetAsDefaultLogger: true}) + app := fx.New( fx.NopLogger, - fx.Provide(func() logging.Logger { - return logger + fx.Provide(func() (logging.Logger, error) { + return logging.New(&logging.Options{Name: "infra", Dev: isDev}) }), - fx.Provide(func() *slog.Logger { - return logging.NewSlogLogger(logging.SlogOptions{ - ShowCaller: true, - ShowDebugLogs: debug, - SetAsDefaultLogger: true, - }) - }), + fx.Supply(logger), fx.Provide(func() (*env.Env, error) { e, err := env.LoadEnv() @@ -93,10 +90,10 @@ func main() { defer cancel() if err := app.Start(ctx); err != nil { - logger.Errorf(err, "failed to start app") + logger.Error("failed to start infra api, got", "err", err) os.Exit(1) } - common.PrintReadyBanner() + common.PrintReadyBanner2(time.Since(start)) <-app.Done() } diff --git a/apps/infra/protobufs/infra.proto b/apps/infra/protobufs/infra.proto new file mode 100644 index 000000000..068d71d7d --- /dev/null +++ b/apps/infra/protobufs/infra.proto @@ -0,0 +1,87 @@ +syntax = "proto3"; + +import "google/protobuf/timestamp.proto"; + +option go_package = "./infra"; + +service Infra { + rpc GetCluster(GetClusterIn) returns (GetClusterOut); + rpc GetNodepool(GetNodepoolIn) returns (GetNodepoolOut); + rpc ClusterExists(ClusterExistsIn) returns (ClusterExistsOut); + rpc GetClusterKubeconfig(GetClusterIn) returns (GetClusterKubeconfigOut); + rpc MarkClusterOnlineAt(MarkClusterOnlineAtIn) returns (MarkClusterOnlineAtOut); + + rpc EnsureGlobalVPNConnection(EnsureGlobalVPNConnectionIn) returns (EnsureGlobalVPNConnectionOut); +} + +message GetClusterIn { + string userId = 1; + string userName = 2; + string userEmail = 3; + + string accountName = 4; + string clusterName = 5; +} + +message GetClusterOut { + string messageQueueTopic = 1; + string dnsHost = 2; + + string IACJobName = 3; + string IACJobNamespace = 4; +} + +message GetNodepoolIn { + string userId = 1; + string userName = 2; + string userEmail = 3; + + string accountName = 4; + string clusterName = 5; + string nodepoolName = 6; +} + +message GetNodepoolOut { + string IACJobName = 1; + string IACJobNamespace = 2; +} + +message ClusterExistsIn { + string userId = 1; + string userName = 2; + string userEmail = 3; + + string accountName = 4; + string clusterName = 5; +} + +message ClusterExistsOut { + bool exists = 1; +} + +message GetClusterKubeconfigOut { + bytes kubeconfig = 1; +} + +message MarkClusterOnlineAtIn { + string accountName = 1; + string clusterName = 2; + google.protobuf.Timestamp timestamp = 3; +} + +message MarkClusterOnlineAtOut {} + +message EnsureGlobalVPNConnectionIn { + string userId = 1; + string userName = 2; + string userEmail = 3; + + string accountName = 4; + string clusterName = 5; + string globalVPNName = 6; + + string dispatchAddr_AccountName = 7; + string dispatchAddr_ClusterName = 8; +} + +message EnsureGlobalVPNConnectionOut {} diff --git a/apps/infra/protobufs/infra/infra.pb.go b/apps/infra/protobufs/infra/infra.pb.go new file mode 100644 index 000000000..81dfa38bb --- /dev/null +++ b/apps/infra/protobufs/infra/infra.pb.go @@ -0,0 +1,1060 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.24.4 +// source: infra.proto + +package infra + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetClusterIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId string `protobuf:"bytes,1,opt,name=userId,proto3" json:"userId,omitempty"` + UserName string `protobuf:"bytes,2,opt,name=userName,proto3" json:"userName,omitempty"` + UserEmail string `protobuf:"bytes,3,opt,name=userEmail,proto3" json:"userEmail,omitempty"` + AccountName string `protobuf:"bytes,4,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,5,opt,name=clusterName,proto3" json:"clusterName,omitempty"` +} + +func (x *GetClusterIn) Reset() { + *x = GetClusterIn{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClusterIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClusterIn) ProtoMessage() {} + +func (x *GetClusterIn) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClusterIn.ProtoReflect.Descriptor instead. +func (*GetClusterIn) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{0} +} + +func (x *GetClusterIn) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *GetClusterIn) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *GetClusterIn) GetUserEmail() string { + if x != nil { + return x.UserEmail + } + return "" +} + +func (x *GetClusterIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *GetClusterIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +type GetClusterOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MessageQueueTopic string `protobuf:"bytes,1,opt,name=messageQueueTopic,proto3" json:"messageQueueTopic,omitempty"` + DnsHost string `protobuf:"bytes,2,opt,name=dnsHost,proto3" json:"dnsHost,omitempty"` + IACJobName string `protobuf:"bytes,3,opt,name=IACJobName,proto3" json:"IACJobName,omitempty"` + IACJobNamespace string `protobuf:"bytes,4,opt,name=IACJobNamespace,proto3" json:"IACJobNamespace,omitempty"` +} + +func (x *GetClusterOut) Reset() { + *x = GetClusterOut{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClusterOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClusterOut) ProtoMessage() {} + +func (x *GetClusterOut) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClusterOut.ProtoReflect.Descriptor instead. +func (*GetClusterOut) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{1} +} + +func (x *GetClusterOut) GetMessageQueueTopic() string { + if x != nil { + return x.MessageQueueTopic + } + return "" +} + +func (x *GetClusterOut) GetDnsHost() string { + if x != nil { + return x.DnsHost + } + return "" +} + +func (x *GetClusterOut) GetIACJobName() string { + if x != nil { + return x.IACJobName + } + return "" +} + +func (x *GetClusterOut) GetIACJobNamespace() string { + if x != nil { + return x.IACJobNamespace + } + return "" +} + +type GetNodepoolIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId string `protobuf:"bytes,1,opt,name=userId,proto3" json:"userId,omitempty"` + UserName string `protobuf:"bytes,2,opt,name=userName,proto3" json:"userName,omitempty"` + UserEmail string `protobuf:"bytes,3,opt,name=userEmail,proto3" json:"userEmail,omitempty"` + AccountName string `protobuf:"bytes,4,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,5,opt,name=clusterName,proto3" json:"clusterName,omitempty"` + NodepoolName string `protobuf:"bytes,6,opt,name=nodepoolName,proto3" json:"nodepoolName,omitempty"` +} + +func (x *GetNodepoolIn) Reset() { + *x = GetNodepoolIn{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodepoolIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodepoolIn) ProtoMessage() {} + +func (x *GetNodepoolIn) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodepoolIn.ProtoReflect.Descriptor instead. +func (*GetNodepoolIn) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{2} +} + +func (x *GetNodepoolIn) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *GetNodepoolIn) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *GetNodepoolIn) GetUserEmail() string { + if x != nil { + return x.UserEmail + } + return "" +} + +func (x *GetNodepoolIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *GetNodepoolIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +func (x *GetNodepoolIn) GetNodepoolName() string { + if x != nil { + return x.NodepoolName + } + return "" +} + +type GetNodepoolOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IACJobName string `protobuf:"bytes,1,opt,name=IACJobName,proto3" json:"IACJobName,omitempty"` + IACJobNamespace string `protobuf:"bytes,2,opt,name=IACJobNamespace,proto3" json:"IACJobNamespace,omitempty"` +} + +func (x *GetNodepoolOut) Reset() { + *x = GetNodepoolOut{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodepoolOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodepoolOut) ProtoMessage() {} + +func (x *GetNodepoolOut) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodepoolOut.ProtoReflect.Descriptor instead. +func (*GetNodepoolOut) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{3} +} + +func (x *GetNodepoolOut) GetIACJobName() string { + if x != nil { + return x.IACJobName + } + return "" +} + +func (x *GetNodepoolOut) GetIACJobNamespace() string { + if x != nil { + return x.IACJobNamespace + } + return "" +} + +type ClusterExistsIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId string `protobuf:"bytes,1,opt,name=userId,proto3" json:"userId,omitempty"` + UserName string `protobuf:"bytes,2,opt,name=userName,proto3" json:"userName,omitempty"` + UserEmail string `protobuf:"bytes,3,opt,name=userEmail,proto3" json:"userEmail,omitempty"` + AccountName string `protobuf:"bytes,4,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,5,opt,name=clusterName,proto3" json:"clusterName,omitempty"` +} + +func (x *ClusterExistsIn) Reset() { + *x = ClusterExistsIn{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterExistsIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterExistsIn) ProtoMessage() {} + +func (x *ClusterExistsIn) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterExistsIn.ProtoReflect.Descriptor instead. +func (*ClusterExistsIn) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{4} +} + +func (x *ClusterExistsIn) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *ClusterExistsIn) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *ClusterExistsIn) GetUserEmail() string { + if x != nil { + return x.UserEmail + } + return "" +} + +func (x *ClusterExistsIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *ClusterExistsIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +type ClusterExistsOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Exists bool `protobuf:"varint,1,opt,name=exists,proto3" json:"exists,omitempty"` +} + +func (x *ClusterExistsOut) Reset() { + *x = ClusterExistsOut{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterExistsOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterExistsOut) ProtoMessage() {} + +func (x *ClusterExistsOut) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterExistsOut.ProtoReflect.Descriptor instead. +func (*ClusterExistsOut) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{5} +} + +func (x *ClusterExistsOut) GetExists() bool { + if x != nil { + return x.Exists + } + return false +} + +type GetClusterKubeconfigOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Kubeconfig []byte `protobuf:"bytes,1,opt,name=kubeconfig,proto3" json:"kubeconfig,omitempty"` +} + +func (x *GetClusterKubeconfigOut) Reset() { + *x = GetClusterKubeconfigOut{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetClusterKubeconfigOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetClusterKubeconfigOut) ProtoMessage() {} + +func (x *GetClusterKubeconfigOut) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetClusterKubeconfigOut.ProtoReflect.Descriptor instead. +func (*GetClusterKubeconfigOut) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{6} +} + +func (x *GetClusterKubeconfigOut) GetKubeconfig() []byte { + if x != nil { + return x.Kubeconfig + } + return nil +} + +type MarkClusterOnlineAtIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccountName string `protobuf:"bytes,1,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,2,opt,name=clusterName,proto3" json:"clusterName,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` +} + +func (x *MarkClusterOnlineAtIn) Reset() { + *x = MarkClusterOnlineAtIn{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MarkClusterOnlineAtIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MarkClusterOnlineAtIn) ProtoMessage() {} + +func (x *MarkClusterOnlineAtIn) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MarkClusterOnlineAtIn.ProtoReflect.Descriptor instead. +func (*MarkClusterOnlineAtIn) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{7} +} + +func (x *MarkClusterOnlineAtIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *MarkClusterOnlineAtIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +func (x *MarkClusterOnlineAtIn) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +type MarkClusterOnlineAtOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *MarkClusterOnlineAtOut) Reset() { + *x = MarkClusterOnlineAtOut{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MarkClusterOnlineAtOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MarkClusterOnlineAtOut) ProtoMessage() {} + +func (x *MarkClusterOnlineAtOut) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MarkClusterOnlineAtOut.ProtoReflect.Descriptor instead. +func (*MarkClusterOnlineAtOut) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{8} +} + +type EnsureGlobalVPNConnectionIn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId string `protobuf:"bytes,1,opt,name=userId,proto3" json:"userId,omitempty"` + UserName string `protobuf:"bytes,2,opt,name=userName,proto3" json:"userName,omitempty"` + UserEmail string `protobuf:"bytes,3,opt,name=userEmail,proto3" json:"userEmail,omitempty"` + AccountName string `protobuf:"bytes,4,opt,name=accountName,proto3" json:"accountName,omitempty"` + ClusterName string `protobuf:"bytes,5,opt,name=clusterName,proto3" json:"clusterName,omitempty"` + GlobalVPNName string `protobuf:"bytes,6,opt,name=globalVPNName,proto3" json:"globalVPNName,omitempty"` + DispatchAddr_AccountName string `protobuf:"bytes,7,opt,name=dispatchAddr_AccountName,json=dispatchAddrAccountName,proto3" json:"dispatchAddr_AccountName,omitempty"` + DispatchAddr_ClusterName string `protobuf:"bytes,8,opt,name=dispatchAddr_ClusterName,json=dispatchAddrClusterName,proto3" json:"dispatchAddr_ClusterName,omitempty"` +} + +func (x *EnsureGlobalVPNConnectionIn) Reset() { + *x = EnsureGlobalVPNConnectionIn{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnsureGlobalVPNConnectionIn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnsureGlobalVPNConnectionIn) ProtoMessage() {} + +func (x *EnsureGlobalVPNConnectionIn) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnsureGlobalVPNConnectionIn.ProtoReflect.Descriptor instead. +func (*EnsureGlobalVPNConnectionIn) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{9} +} + +func (x *EnsureGlobalVPNConnectionIn) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetUserEmail() string { + if x != nil { + return x.UserEmail + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetAccountName() string { + if x != nil { + return x.AccountName + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetClusterName() string { + if x != nil { + return x.ClusterName + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetGlobalVPNName() string { + if x != nil { + return x.GlobalVPNName + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetDispatchAddr_AccountName() string { + if x != nil { + return x.DispatchAddr_AccountName + } + return "" +} + +func (x *EnsureGlobalVPNConnectionIn) GetDispatchAddr_ClusterName() string { + if x != nil { + return x.DispatchAddr_ClusterName + } + return "" +} + +type EnsureGlobalVPNConnectionOut struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EnsureGlobalVPNConnectionOut) Reset() { + *x = EnsureGlobalVPNConnectionOut{} + if protoimpl.UnsafeEnabled { + mi := &file_infra_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnsureGlobalVPNConnectionOut) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnsureGlobalVPNConnectionOut) ProtoMessage() {} + +func (x *EnsureGlobalVPNConnectionOut) ProtoReflect() protoreflect.Message { + mi := &file_infra_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnsureGlobalVPNConnectionOut.ProtoReflect.Descriptor instead. +func (*EnsureGlobalVPNConnectionOut) Descriptor() ([]byte, []int) { + return file_infra_proto_rawDescGZIP(), []int{10} +} + +var File_infra_proto protoreflect.FileDescriptor + +var file_infra_proto_rawDesc = []byte{ + 0x0a, 0x0b, 0x69, 0x6e, 0x66, 0x72, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa4, + 0x01, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, + 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x11, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, + 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6e, 0x73, 0x48, 0x6f, 0x73, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6e, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x12, + 0x1e, 0x0a, 0x0a, 0x49, 0x41, 0x43, 0x4a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x49, 0x41, 0x43, 0x4a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x28, 0x0a, 0x0f, 0x49, 0x41, 0x43, 0x4a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x49, 0x41, 0x43, 0x4a, 0x6f, 0x62, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x47, 0x65, + 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x20, 0x0a, + 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x6f, 0x6c, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x6f, + 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, + 0x70, 0x6f, 0x6f, 0x6c, 0x4f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49, 0x41, 0x43, 0x4a, 0x6f, + 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x49, 0x41, 0x43, + 0x4a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x49, 0x41, 0x43, 0x4a, 0x6f, + 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x49, 0x41, 0x43, 0x4a, 0x6f, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x22, 0xa7, 0x01, 0x0a, 0x0f, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x69, + 0x73, 0x74, 0x73, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, + 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x4f, 0x75, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x39, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4f, + 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x22, 0x95, 0x01, 0x0a, 0x15, 0x4d, 0x61, 0x72, 0x6b, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x41, 0x74, 0x49, 0x6e, 0x12, 0x20, 0x0a, 0x0b, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x18, 0x0a, 0x16, 0x4d, 0x61, + 0x72, 0x6b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x41, + 0x74, 0x4f, 0x75, 0x74, 0x22, 0xcf, 0x02, 0x0a, 0x1b, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x47, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, + 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, + 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x67, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x39, 0x0a, 0x18, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x41, 0x64, 0x64, 0x72, + 0x5f, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x17, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x41, 0x64, 0x64, 0x72, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x18, 0x64, + 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x41, 0x64, 0x64, 0x72, 0x5f, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x64, + 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x41, 0x64, 0x64, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x1c, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x32, 0xfd, 0x02, 0x0a, 0x05, 0x49, 0x6e, 0x66, 0x72, 0x61, + 0x12, 0x2b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x0d, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x1a, 0x0e, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x12, 0x2e, 0x0a, + 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0x0e, 0x2e, 0x47, + 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x6e, 0x1a, 0x0f, 0x2e, 0x47, + 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x6f, 0x6c, 0x4f, 0x75, 0x74, 0x12, 0x34, 0x0a, + 0x0d, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x10, + 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x49, 0x6e, + 0x1a, 0x11, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, + 0x4f, 0x75, 0x74, 0x12, 0x3f, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0d, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x1a, 0x18, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x4f, 0x75, 0x74, 0x12, 0x46, 0x0a, 0x13, 0x4d, 0x61, 0x72, 0x6b, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x41, 0x74, 0x12, 0x16, 0x2e, 0x4d, 0x61, + 0x72, 0x6b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x41, + 0x74, 0x49, 0x6e, 0x1a, 0x17, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x41, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x58, 0x0a, 0x19, + 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x45, 0x6e, 0x73, 0x75, + 0x72, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x1a, 0x1d, 0x2e, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x56, 0x50, 0x4e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x69, 0x6e, 0x66, 0x72, + 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_infra_proto_rawDescOnce sync.Once + file_infra_proto_rawDescData = file_infra_proto_rawDesc +) + +func file_infra_proto_rawDescGZIP() []byte { + file_infra_proto_rawDescOnce.Do(func() { + file_infra_proto_rawDescData = protoimpl.X.CompressGZIP(file_infra_proto_rawDescData) + }) + return file_infra_proto_rawDescData +} + +var file_infra_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_infra_proto_goTypes = []interface{}{ + (*GetClusterIn)(nil), // 0: GetClusterIn + (*GetClusterOut)(nil), // 1: GetClusterOut + (*GetNodepoolIn)(nil), // 2: GetNodepoolIn + (*GetNodepoolOut)(nil), // 3: GetNodepoolOut + (*ClusterExistsIn)(nil), // 4: ClusterExistsIn + (*ClusterExistsOut)(nil), // 5: ClusterExistsOut + (*GetClusterKubeconfigOut)(nil), // 6: GetClusterKubeconfigOut + (*MarkClusterOnlineAtIn)(nil), // 7: MarkClusterOnlineAtIn + (*MarkClusterOnlineAtOut)(nil), // 8: MarkClusterOnlineAtOut + (*EnsureGlobalVPNConnectionIn)(nil), // 9: EnsureGlobalVPNConnectionIn + (*EnsureGlobalVPNConnectionOut)(nil), // 10: EnsureGlobalVPNConnectionOut + (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp +} +var file_infra_proto_depIdxs = []int32{ + 11, // 0: MarkClusterOnlineAtIn.timestamp:type_name -> google.protobuf.Timestamp + 0, // 1: Infra.GetCluster:input_type -> GetClusterIn + 2, // 2: Infra.GetNodepool:input_type -> GetNodepoolIn + 4, // 3: Infra.ClusterExists:input_type -> ClusterExistsIn + 0, // 4: Infra.GetClusterKubeconfig:input_type -> GetClusterIn + 7, // 5: Infra.MarkClusterOnlineAt:input_type -> MarkClusterOnlineAtIn + 9, // 6: Infra.EnsureGlobalVPNConnection:input_type -> EnsureGlobalVPNConnectionIn + 1, // 7: Infra.GetCluster:output_type -> GetClusterOut + 3, // 8: Infra.GetNodepool:output_type -> GetNodepoolOut + 5, // 9: Infra.ClusterExists:output_type -> ClusterExistsOut + 6, // 10: Infra.GetClusterKubeconfig:output_type -> GetClusterKubeconfigOut + 8, // 11: Infra.MarkClusterOnlineAt:output_type -> MarkClusterOnlineAtOut + 10, // 12: Infra.EnsureGlobalVPNConnection:output_type -> EnsureGlobalVPNConnectionOut + 7, // [7:13] is the sub-list for method output_type + 1, // [1:7] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_infra_proto_init() } +func file_infra_proto_init() { + if File_infra_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_infra_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClusterIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClusterOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodepoolIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetNodepoolOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClusterExistsIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClusterExistsOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetClusterKubeconfigOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MarkClusterOnlineAtIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MarkClusterOnlineAtOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnsureGlobalVPNConnectionIn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_infra_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnsureGlobalVPNConnectionOut); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_infra_proto_rawDesc, + NumEnums: 0, + NumMessages: 11, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_infra_proto_goTypes, + DependencyIndexes: file_infra_proto_depIdxs, + MessageInfos: file_infra_proto_msgTypes, + }.Build() + File_infra_proto = out.File + file_infra_proto_rawDesc = nil + file_infra_proto_goTypes = nil + file_infra_proto_depIdxs = nil +} diff --git a/apps/infra/protobufs/infra/infra_grpc.pb.go b/apps/infra/protobufs/infra/infra_grpc.pb.go new file mode 100644 index 000000000..1d2d625c6 --- /dev/null +++ b/apps/infra/protobufs/infra/infra_grpc.pb.go @@ -0,0 +1,294 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.24.4 +// source: infra.proto + +package infra + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + Infra_GetCluster_FullMethodName = "/Infra/GetCluster" + Infra_GetNodepool_FullMethodName = "/Infra/GetNodepool" + Infra_ClusterExists_FullMethodName = "/Infra/ClusterExists" + Infra_GetClusterKubeconfig_FullMethodName = "/Infra/GetClusterKubeconfig" + Infra_MarkClusterOnlineAt_FullMethodName = "/Infra/MarkClusterOnlineAt" + Infra_EnsureGlobalVPNConnection_FullMethodName = "/Infra/EnsureGlobalVPNConnection" +) + +// InfraClient is the client API for Infra service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type InfraClient interface { + GetCluster(ctx context.Context, in *GetClusterIn, opts ...grpc.CallOption) (*GetClusterOut, error) + GetNodepool(ctx context.Context, in *GetNodepoolIn, opts ...grpc.CallOption) (*GetNodepoolOut, error) + ClusterExists(ctx context.Context, in *ClusterExistsIn, opts ...grpc.CallOption) (*ClusterExistsOut, error) + GetClusterKubeconfig(ctx context.Context, in *GetClusterIn, opts ...grpc.CallOption) (*GetClusterKubeconfigOut, error) + MarkClusterOnlineAt(ctx context.Context, in *MarkClusterOnlineAtIn, opts ...grpc.CallOption) (*MarkClusterOnlineAtOut, error) + EnsureGlobalVPNConnection(ctx context.Context, in *EnsureGlobalVPNConnectionIn, opts ...grpc.CallOption) (*EnsureGlobalVPNConnectionOut, error) +} + +type infraClient struct { + cc grpc.ClientConnInterface +} + +func NewInfraClient(cc grpc.ClientConnInterface) InfraClient { + return &infraClient{cc} +} + +func (c *infraClient) GetCluster(ctx context.Context, in *GetClusterIn, opts ...grpc.CallOption) (*GetClusterOut, error) { + out := new(GetClusterOut) + err := c.cc.Invoke(ctx, Infra_GetCluster_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *infraClient) GetNodepool(ctx context.Context, in *GetNodepoolIn, opts ...grpc.CallOption) (*GetNodepoolOut, error) { + out := new(GetNodepoolOut) + err := c.cc.Invoke(ctx, Infra_GetNodepool_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *infraClient) ClusterExists(ctx context.Context, in *ClusterExistsIn, opts ...grpc.CallOption) (*ClusterExistsOut, error) { + out := new(ClusterExistsOut) + err := c.cc.Invoke(ctx, Infra_ClusterExists_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *infraClient) GetClusterKubeconfig(ctx context.Context, in *GetClusterIn, opts ...grpc.CallOption) (*GetClusterKubeconfigOut, error) { + out := new(GetClusterKubeconfigOut) + err := c.cc.Invoke(ctx, Infra_GetClusterKubeconfig_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *infraClient) MarkClusterOnlineAt(ctx context.Context, in *MarkClusterOnlineAtIn, opts ...grpc.CallOption) (*MarkClusterOnlineAtOut, error) { + out := new(MarkClusterOnlineAtOut) + err := c.cc.Invoke(ctx, Infra_MarkClusterOnlineAt_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *infraClient) EnsureGlobalVPNConnection(ctx context.Context, in *EnsureGlobalVPNConnectionIn, opts ...grpc.CallOption) (*EnsureGlobalVPNConnectionOut, error) { + out := new(EnsureGlobalVPNConnectionOut) + err := c.cc.Invoke(ctx, Infra_EnsureGlobalVPNConnection_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// InfraServer is the server API for Infra service. +// All implementations must embed UnimplementedInfraServer +// for forward compatibility +type InfraServer interface { + GetCluster(context.Context, *GetClusterIn) (*GetClusterOut, error) + GetNodepool(context.Context, *GetNodepoolIn) (*GetNodepoolOut, error) + ClusterExists(context.Context, *ClusterExistsIn) (*ClusterExistsOut, error) + GetClusterKubeconfig(context.Context, *GetClusterIn) (*GetClusterKubeconfigOut, error) + MarkClusterOnlineAt(context.Context, *MarkClusterOnlineAtIn) (*MarkClusterOnlineAtOut, error) + EnsureGlobalVPNConnection(context.Context, *EnsureGlobalVPNConnectionIn) (*EnsureGlobalVPNConnectionOut, error) + mustEmbedUnimplementedInfraServer() +} + +// UnimplementedInfraServer must be embedded to have forward compatible implementations. +type UnimplementedInfraServer struct { +} + +func (UnimplementedInfraServer) GetCluster(context.Context, *GetClusterIn) (*GetClusterOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCluster not implemented") +} +func (UnimplementedInfraServer) GetNodepool(context.Context, *GetNodepoolIn) (*GetNodepoolOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNodepool not implemented") +} +func (UnimplementedInfraServer) ClusterExists(context.Context, *ClusterExistsIn) (*ClusterExistsOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClusterExists not implemented") +} +func (UnimplementedInfraServer) GetClusterKubeconfig(context.Context, *GetClusterIn) (*GetClusterKubeconfigOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetClusterKubeconfig not implemented") +} +func (UnimplementedInfraServer) MarkClusterOnlineAt(context.Context, *MarkClusterOnlineAtIn) (*MarkClusterOnlineAtOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method MarkClusterOnlineAt not implemented") +} +func (UnimplementedInfraServer) EnsureGlobalVPNConnection(context.Context, *EnsureGlobalVPNConnectionIn) (*EnsureGlobalVPNConnectionOut, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnsureGlobalVPNConnection not implemented") +} +func (UnimplementedInfraServer) mustEmbedUnimplementedInfraServer() {} + +// UnsafeInfraServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to InfraServer will +// result in compilation errors. +type UnsafeInfraServer interface { + mustEmbedUnimplementedInfraServer() +} + +func RegisterInfraServer(s grpc.ServiceRegistrar, srv InfraServer) { + s.RegisterService(&Infra_ServiceDesc, srv) +} + +func _Infra_GetCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetClusterIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InfraServer).GetCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Infra_GetCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InfraServer).GetCluster(ctx, req.(*GetClusterIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Infra_GetNodepool_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNodepoolIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InfraServer).GetNodepool(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Infra_GetNodepool_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InfraServer).GetNodepool(ctx, req.(*GetNodepoolIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Infra_ClusterExists_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ClusterExistsIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InfraServer).ClusterExists(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Infra_ClusterExists_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InfraServer).ClusterExists(ctx, req.(*ClusterExistsIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Infra_GetClusterKubeconfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetClusterIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InfraServer).GetClusterKubeconfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Infra_GetClusterKubeconfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InfraServer).GetClusterKubeconfig(ctx, req.(*GetClusterIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Infra_MarkClusterOnlineAt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MarkClusterOnlineAtIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InfraServer).MarkClusterOnlineAt(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Infra_MarkClusterOnlineAt_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InfraServer).MarkClusterOnlineAt(ctx, req.(*MarkClusterOnlineAtIn)) + } + return interceptor(ctx, in, info, handler) +} + +func _Infra_EnsureGlobalVPNConnection_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnsureGlobalVPNConnectionIn) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InfraServer).EnsureGlobalVPNConnection(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Infra_EnsureGlobalVPNConnection_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InfraServer).EnsureGlobalVPNConnection(ctx, req.(*EnsureGlobalVPNConnectionIn)) + } + return interceptor(ctx, in, info, handler) +} + +// Infra_ServiceDesc is the grpc.ServiceDesc for Infra service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Infra_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "Infra", + HandlerType: (*InfraServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetCluster", + Handler: _Infra_GetCluster_Handler, + }, + { + MethodName: "GetNodepool", + Handler: _Infra_GetNodepool_Handler, + }, + { + MethodName: "ClusterExists", + Handler: _Infra_ClusterExists_Handler, + }, + { + MethodName: "GetClusterKubeconfig", + Handler: _Infra_GetClusterKubeconfig_Handler, + }, + { + MethodName: "MarkClusterOnlineAt", + Handler: _Infra_MarkClusterOnlineAt_Handler, + }, + { + MethodName: "EnsureGlobalVPNConnection", + Handler: _Infra_EnsureGlobalVPNConnection_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "infra.proto", +} From 76452a1cd29a456075e0443917c1b79f04edb576 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Sat, 14 Sep 2024 02:32:16 +0530 Subject: [PATCH 11/17] feat(tenant-agent): improves logging --- apps/tenant-agent/main.go | 25 ++++++++++++++++--------- apps/tenant-agent/types/types.go | 4 ++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/apps/tenant-agent/main.go b/apps/tenant-agent/main.go index 0df7629d5..c0a9219b4 100644 --- a/apps/tenant-agent/main.go +++ b/apps/tenant-agent/main.go @@ -57,7 +57,6 @@ const ( func (g *grpcHandler) handleErrorOnApply(ctx context.Context, err error, msg t.AgentMessage) error { b, err := json.Marshal(t.AgentErrMessage{ AccountName: msg.AccountName, - ClusterName: msg.ClusterName, Error: err.Error(), Action: msg.Action, Object: msg.Object, @@ -80,7 +79,7 @@ func NewAuthorizedGrpcContext(ctx context.Context, accessToken string) context.C func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) error { g.incrementCounter() start := time.Now() - logger := g.logger.With("counter", g.inMemCounter, "account", msg.AccountName, "cluster", msg.ClusterName, "action", msg.Action) + logger := g.logger.With("counter", g.inMemCounter, "account", msg.AccountName, "action", msg.Action) ctx, cf := func() (context.Context, context.CancelFunc) { if g.isDev { return context.WithCancel(gctx) @@ -95,7 +94,7 @@ func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) er } obj := unstructured.Unstructured{Object: msg.Object} - mLogger := logger.With("gvk", obj.GetObjectKind().GroupVersionKind().String()) + mLogger := logger.With("gvk", obj.GetObjectKind().GroupVersionKind().String()).With("NN", fmt.Sprintf("%s/%s", obj.GetNamespace(), obj.GetName())) mLogger.Info("received message") @@ -106,6 +105,13 @@ func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) er switch msg.Action { case t.ActionApply: { + // lb := obj.GetLabels() + // if lb == nil { + // lb = make(map[string]string, 1) + // } + // lb[constants.AccountNameKey] = msg.AccountName + // obj.SetLabels(lb) + b, err := yaml.Marshal(msg.Object) if err != nil { return g.handleErrorOnApply(ctx, err, msg) @@ -113,11 +119,9 @@ func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) er if _, err := g.yamlClient.ApplyYAML(ctx, b); err != nil { // mLogger.Errorf(err, "[%d] [error-on-apply]: yaml: \n%s\n", g.inMemCounter, b) - mLogger.Info("failed to process message") - fmt.Printf("[error-on-apply] yaml: \n%s\n", b) + mLogger.Error("failed to process message, got", "err", err, "error-on-apply:YAML", fmt.Sprintf("\n%s\n", b)) return g.handleErrorOnApply(ctx, err, msg) } - mLogger.Info("processed message") } case t.ActionDelete: { @@ -127,9 +131,9 @@ func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) er mLogger.Info("processed message, resource does not exist, might already be deleted") return g.handleErrorOnApply(ctx, err, msg) } - mLogger.Info("failed to process message") + mLogger.Error("failed to process message, got", "err", err) + return g.handleErrorOnApply(ctx, err, msg) } - mLogger.Info("processed message") } case t.ActionRestart: { @@ -280,6 +284,9 @@ func main() { flag.Parse() + start := time.Now() + common.PrintBuildInfo() + ev := env.GetEnvOrDie() logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug}) @@ -327,7 +334,7 @@ func main() { } }() - common.PrintReadyBanner() + common.PrintReadyBanner2(time.Since(start)) for { cc, err := libGrpc.NewGrpcClientV2(ev.GrpcAddr, libGrpc.GrpcConnectOpts{TLSConnect: !isDev, Logger: logger}) diff --git a/apps/tenant-agent/types/types.go b/apps/tenant-agent/types/types.go index c0a3b2855..5a0bb8b5c 100644 --- a/apps/tenant-agent/types/types.go +++ b/apps/tenant-agent/types/types.go @@ -10,7 +10,7 @@ const ( type AgentMessage struct { AccountName string `json:"accountName"` - ClusterName string `json:"clusterName"` + // ClusterName string `json:"clusterName"` Action Action `json:"action"` Object map[string]any `json:"object"` @@ -18,7 +18,7 @@ type AgentMessage struct { type AgentErrMessage struct { AccountName string `json:"accountName"` - ClusterName string `json:"clusterName"` + // ClusterName string `json:"clusterName"` Error string `json:"error"` Action Action `json:"action"` From 1a3c6fc4ce697e17f2668a3a1961d4f44a897012 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Tue, 17 Sep 2024 17:28:15 +0530 Subject: [PATCH 12/17] feat(accounts): removes container registry api requirements --- .../internal/app/graph/schema.resolvers.go | 9 ++- apps/accounts/internal/domain/accounts.go | 67 +++++++++---------- apps/accounts/internal/domain/domain.go | 23 +++---- apps/accounts/internal/env/env.go | 10 +-- apps/accounts/internal/framework/framework.go | 15 +++-- 5 files changed, 63 insertions(+), 61 deletions(-) diff --git a/apps/accounts/internal/app/graph/schema.resolvers.go b/apps/accounts/internal/app/graph/schema.resolvers.go index e66c52648..ee7b8e5ac 100644 --- a/apps/accounts/internal/app/graph/schema.resolvers.go +++ b/apps/accounts/internal/app/graph/schema.resolvers.go @@ -6,6 +6,7 @@ package graph import ( "context" + "github.com/kloudlite/api/apps/accounts/internal/app/graph/generated" "github.com/kloudlite/api/apps/accounts/internal/app/graph/model" "github.com/kloudlite/api/apps/accounts/internal/domain" @@ -302,6 +303,8 @@ func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } // User returns generated.UserResolver implementation. func (r *Resolver) User() generated.UserResolver { return &userResolver{r} } -type mutationResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } -type userResolver struct{ *Resolver } +type ( + mutationResolver struct{ *Resolver } + queryResolver struct{ *Resolver } + userResolver struct{ *Resolver } +) diff --git a/apps/accounts/internal/domain/accounts.go b/apps/accounts/internal/domain/accounts.go index 4f28d10c9..11d4f3256 100644 --- a/apps/accounts/internal/domain/accounts.go +++ b/apps/accounts/internal/domain/accounts.go @@ -13,7 +13,6 @@ import ( iamT "github.com/kloudlite/api/apps/iam/types" "github.com/kloudlite/api/common" "github.com/kloudlite/api/constants" - "github.com/kloudlite/api/grpc-interfaces/container_registry" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" fn "github.com/kloudlite/api/pkg/functions" "github.com/kloudlite/api/pkg/repos" @@ -108,33 +107,33 @@ func (d *domain) ensureKloudliteRegistryCredentials(ctx UserContext, account *en return nil } - out, err := d.containerRegistryClient.CreateReadOnlyCredential(ctx, &container_registry.CreateReadOnlyCredentialIn{ - AccountName: account.Name, - UserId: string(ctx.UserId), - CredentialName: credentialsName, - RegistryUsername: fmt.Sprintf("account_%s", account.Name), - }) - if err != nil { - return err - } - - if err := d.k8sClient.Create(ctx, &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "Secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: credentialsName, - Namespace: account.TargetNamespace, - }, - Immutable: new(bool), - Data: map[string][]byte{ - corev1.DockerConfigJsonKey: []byte(out.DockerConfigJson), - }, - Type: corev1.SecretTypeDockerConfigJson, - }); err != nil { - return err - } + // out, err := d.containerRegistryClient.CreateReadOnlyCredential(ctx, &container_registry.CreateReadOnlyCredentialIn{ + // AccountName: account.Name, + // UserId: string(ctx.UserId), + // CredentialName: credentialsName, + // RegistryUsername: fmt.Sprintf("account_%s", account.Name), + // }) + // if err != nil { + // return err + // } + + // if err := d.k8sClient.Create(ctx, &corev1.Secret{ + // TypeMeta: metav1.TypeMeta{ + // Kind: "Secret", + // APIVersion: "v1", + // }, + // ObjectMeta: metav1.ObjectMeta{ + // Name: credentialsName, + // Namespace: account.TargetNamespace, + // }, + // Immutable: new(bool), + // Data: map[string][]byte{ + // corev1.DockerConfigJsonKey: []byte(out.DockerConfigJson), + // }, + // Type: corev1.SecretTypeDockerConfigJson, + // }); err != nil { + // return err + // } return nil } @@ -167,13 +166,13 @@ func (d *domain) CreateAccount(ctx UserContext, account entities.Account) (*enti return nil, errors.NewE(err) } - if err := d.ensureNamespaceForAccount(ctx, account.Name, account.TargetNamespace); err != nil { - return nil, errors.NewE(err) - } + // if err := d.ensureNamespaceForAccount(ctx, account.Name, account.TargetNamespace); err != nil { + // return nil, errors.NewE(err) + // } - if err := d.ensureKloudliteRegistryCredentials(ctx, &account); err != nil { - return nil, errors.NewE(err) - } + // if err := d.ensureKloudliteRegistryCredentials(ctx, &account); err != nil { + // return nil, errors.NewE(err) + // } return acc, nil } diff --git a/apps/accounts/internal/domain/domain.go b/apps/accounts/internal/domain/domain.go index 511368a95..98b318ccc 100644 --- a/apps/accounts/internal/domain/domain.go +++ b/apps/accounts/internal/domain/domain.go @@ -4,7 +4,6 @@ import ( "github.com/kloudlite/api/apps/accounts/internal/entities" "github.com/kloudlite/api/apps/accounts/internal/env" iamT "github.com/kloudlite/api/apps/iam/types" - "github.com/kloudlite/api/grpc-interfaces/container_registry" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/auth" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/comms" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/console" @@ -73,11 +72,11 @@ type Domain interface { } type domain struct { - authClient auth.AuthClient - iamClient iam.IAMClient - consoleClient console.ConsoleClient - containerRegistryClient container_registry.ContainerRegistryClient - commsClient comms.CommsClient + authClient auth.AuthClient + iamClient iam.IAMClient + consoleClient console.ConsoleClient + // containerRegistryClient container_registry.ContainerRegistryClient + commsClient comms.CommsClient accountRepo repos.DbRepo[*entities.Account] invitationRepo repos.DbRepo[*entities.Invitation] @@ -93,7 +92,7 @@ type domain struct { func NewDomain( iamCli iam.IAMClient, consoleClient console.ConsoleClient, - containerRegistryClient container_registry.ContainerRegistryClient, + // containerRegistryClient container_registry.ContainerRegistryClient, authClient auth.AuthClient, commsClient comms.CommsClient, @@ -108,11 +107,11 @@ func NewDomain( logger logging.Logger, ) Domain { return &domain{ - authClient: authClient, - iamClient: iamCli, - consoleClient: consoleClient, - commsClient: commsClient, - containerRegistryClient: containerRegistryClient, + authClient: authClient, + iamClient: iamCli, + consoleClient: consoleClient, + commsClient: commsClient, + // containerRegistryClient: containerRegistryClient, k8sClient: k8sClient, diff --git a/apps/accounts/internal/env/env.go b/apps/accounts/internal/env/env.go index f3d17bbf0..2b06baf5e 100644 --- a/apps/accounts/internal/env/env.go +++ b/apps/accounts/internal/env/env.go @@ -19,11 +19,11 @@ type Env struct { CookieDomain string `env:"COOKIE_DOMAIN" required:"true"` - IamGrpcAddr string `env:"IAM_GRPC_ADDR" required:"true"` - CommsGrpcAddr string `env:"COMMS_GRPC_ADDR" required:"true"` - ContainerRegistryGrpcAddr string `env:"CONTAINER_REGISTRY_GRPC_ADDR" required:"true"` - ConsoleGrpcAddr string `env:"CONSOLE_GRPC_ADDR" required:"true"` - AuthGrpcAddr string `env:"AUTH_GRPC_ADDR" required:"true"` + IamGrpcAddr string `env:"IAM_GRPC_ADDR" required:"true"` + CommsGrpcAddr string `env:"COMMS_GRPC_ADDR" required:"true"` + // ContainerRegistryGrpcAddr string `env:"CONTAINER_REGISTRY_GRPC_ADDR" required:"true"` + ConsoleGrpcAddr string `env:"CONSOLE_GRPC_ADDR" required:"true"` + AuthGrpcAddr string `env:"AUTH_GRPC_ADDR" required:"true"` SessionKVBucket string `env:"SESSION_KV_BUCKET" required:"true"` NatsURL string `env:"NATS_URL" required:"true"` diff --git a/apps/accounts/internal/framework/framework.go b/apps/accounts/internal/framework/framework.go index 866c8ddf7..624dfc2cb 100644 --- a/apps/accounts/internal/framework/framework.go +++ b/apps/accounts/internal/framework/framework.go @@ -68,9 +68,9 @@ var Module = fx.Module("framework", return grpc.NewGrpcClient(ev.CommsGrpcAddr) }), - fx.Provide(func(ev *env.Env) (app.ContainerRegistryClient, error) { - return grpc.NewGrpcClient(ev.ContainerRegistryGrpcAddr) - }), + // fx.Provide(func(ev *env.Env) (app.ContainerRegistryClient, error) { + // return grpc.NewGrpcClient(ev.ContainerRegistryGrpcAddr) + // }), fx.Provide(func(ev *env.Env) (app.ConsoleClient, error) { return grpc.NewGrpcClient(ev.ConsoleGrpcAddr) @@ -78,7 +78,8 @@ var Module = fx.Module("framework", app.Module, - fx.Invoke(func(c1 app.AuthClient, c2 app.IAMClient, c3 app.CommsClient, c4 app.ContainerRegistryClient, c5 app.ConsoleClient, lf fx.Lifecycle) { + // fx.Invoke(func(c1 app.AuthClient, c2 app.IAMClient, c3 app.CommsClient, c4 app.ContainerRegistryClient, c5 app.ConsoleClient, lf fx.Lifecycle) { + fx.Invoke(func(c1 app.AuthClient, c2 app.IAMClient, c3 app.CommsClient, c5 app.ConsoleClient, lf fx.Lifecycle) { lf.Append(fx.Hook{ OnStop: func(context.Context) error { if err := c1.Close(); err != nil { @@ -90,9 +91,9 @@ var Module = fx.Module("framework", if err := c3.Close(); err != nil { return errors.NewE(err) } - if err := c4.Close(); err != nil { - return errors.NewE(err) - } + // if err := c4.Close(); err != nil { + // return errors.NewE(err) + // } if err := c5.Close(); err != nil { return errors.NewE(err) } From fd9b0ae7701cccfacf03774b1e5256bfd7545e8c Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Tue, 17 Sep 2024 17:30:31 +0530 Subject: [PATCH 13/17] feat(infra): updates gateway syncing, and supports edge on platform cluster --- apps/infra/Taskfile.yml | 3 +- apps/infra/internal/domain/clusters.go | 219 +++--------------- .../domain/global-vpn-cluster-connection.go | 19 +- .../infra/internal/domain/provider-secrets.go | 3 - apps/infra/internal/env/env.go | 54 +++-- apps/infra/main.go | 2 +- 6 files changed, 79 insertions(+), 221 deletions(-) diff --git a/apps/infra/Taskfile.yml b/apps/infra/Taskfile.yml index c16798cd5..5063ebe79 100644 --- a/apps/infra/Taskfile.yml +++ b/apps/infra/Taskfile.yml @@ -53,7 +53,8 @@ tasks: - .secrets/env cmds: - go build -o bin/infra . - - ./bin/infra --dev + # - ./bin/infra --dev + - ./bin/infra gen:constants: cmds: diff --git a/apps/infra/internal/domain/clusters.go b/apps/infra/internal/domain/clusters.go index 30d42f9b2..c0ac2fc5b 100644 --- a/apps/infra/internal/domain/clusters.go +++ b/apps/infra/internal/domain/clusters.go @@ -33,6 +33,7 @@ import ( corev1 "k8s.io/api/core/v1" apiErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" ) const ( @@ -380,11 +381,6 @@ func (d *domain) syncKloudliteGatewayDevice(ctx InfraContext, gvpnName string) e defer func() { d.logger.Info("syncKloudliteGatewayDevice", "took", fmt.Sprintf("%.2fs", time.Since(t).Seconds())) }() - // 1. parse deployment template - b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) - if err != nil { - return errors.NewE(err) - } svcTemplate, err := templates.Read(templates.GatewayServiceTemplate) if err != nil { @@ -450,7 +446,8 @@ func (d *domain) syncKloudliteGatewayDevice(ctx InfraContext, gvpnName string) e } } - resourceName := fmt.Sprintf("kloudlite-device-%s", gv.Name) + // resourceName := fmt.Sprintf("kloudlite-device-%s", gv.Name) + resourceName := fmt.Sprintf("device-%s-egw", gv.Name) resourceNamespace := accNs selector := map[string]string{ "app": resourceName, @@ -468,194 +465,26 @@ func (d *domain) syncKloudliteGatewayDevice(ctx InfraContext, gvpnName string) e return errors.Newf("invalid gateway region %q", gao.KloudliteGatewayRegion) } - wgEndpoint := gwRegion.PublicDNSHost - - c, err := k8s.RestConfigFromKubeConfig([]byte(gwRegion.Kubeconfig)) - if err != nil { - return errors.NewE(err) - } - - yc, err := kubectl.NewYAMLClient(c, kubectl.YAMLClientOpts{}) - if err != nil { - return errors.NewE(err) - } + var k8sRestConfig *rest.Config - service := &corev1.Service{} - - wgSvcName := fmt.Sprintf("%s-wg", resourceName) - - svcBytes, err := templates.ParseBytes(svcTemplate, templates.GatewayServiceTemplateVars{ - Name: wgSvcName, - Namespace: resourceNamespace, - WireguardPort: wgParams.ListenPort, - Selector: selector, - }) - if err != nil { - return errors.NewE(err) - } - - ctx2, cf := func() (context.Context, context.CancelFunc) { - if d.env.IsDev { - return context.WithCancel(ctx) - } - return context.WithTimeout(ctx, 5*time.Second) - }() - defer cf() - - for { - if ctx2.Err() != nil { - return ctx2.Err() - } - service, err = yc.Client().CoreV1().Services(resourceNamespace).Get(ctx, wgSvcName, metav1.GetOptions{}) + switch gwRegion.ID { + case "self": + k8sRestConfig, err = k8s.RestInclusterConfig() if err != nil { - if !apiErrors.IsNotFound(err) { - return err - } - if _, err := yc.ApplyYAML(ctx, svcBytes); err != nil { + return errors.NewE(err) + } + default: + { + k8sRestConfig, err = k8s.RestConfigFromKubeConfig([]byte(gwRegion.Kubeconfig)) + if err != nil { return errors.NewE(err) } - continue - } - - if service.Spec.Ports[0].NodePort != 0 { - wgEndpoint = fmt.Sprintf("%s:%d", wgEndpoint, service.Spec.Ports[0].NodePort) - break - } - } - - if _, err := d.gvpnDevicesRepo.PatchById(ctx, klDevice.Id, repos.Document{ - fc.GlobalVPNDevicePublicEndpoint: wgEndpoint, - }); err != nil { - return err - } - - wgConfig, err := wgutils.GenerateWireguardConfig(*wgParams) - if err != nil { - return err - } - - deploymentBytes, err := templates.ParseBytes(b, templates.GVPNKloudliteDeviceTemplateVars{ - Name: resourceName, - Namespace: accNs, - WgConfig: wgConfig, - EnableKubeReverseProxy: false, - KubeReverseProxyImage: d.env.GlobalVPNKubeReverseProxyImage, - AuthzToken: d.env.GlobalVPNKubeReverseProxyAuthzToken, - GatewayDNSServers: strings.Join(dnsServerArgs, ","), - GatewayServiceHosts: strings.Join(deviceSvcHosts, ","), - WireguardPort: wgParams.ListenPort, - - KloudliteAccount: gv.AccountName, - }) - if err != nil { - return err - } - - d.logger.Info("applying yaml", "yaml", string(deploymentBytes)) - if _, err := yc.ApplyYAML(ctx, deploymentBytes); err != nil { - return errors.NewE(err) - } - - return nil -} - -func (d *domain) syncKloudliteGatewayDevice2(ctx InfraContext, gvpnName string) error { - t := time.Now() - defer func() { - d.logger.Info("syncKloudliteGatewayDevice2", "took", time.Since(t).Seconds()) - }() - // 1. parse deployment template - b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) - if err != nil { - return errors.NewE(err) - } - - svcTemplate, err := templates.Read(templates.GatewayServiceTemplate) - if err != nil { - return errors.NewE(err) - } - - accNs, err := d.getAccNamespace(ctx) - if err != nil { - return errors.NewE(err) - } - - gv, err := d.findGlobalVPN(ctx, gvpnName) - if err != nil { - return err - } - - if gv.KloudliteGatewayDevice.Name == "" { - return nil - } - - gvpnConns, err := d.listGlobalVPNConnections(ctx, gvpnName) - if err != nil { - return err - } - - klDevice, err := d.findGlobalVPNDevice(ctx, gvpnName, gv.KloudliteGatewayDevice.Name) - if err != nil { - return err - } - - clDevice, err := d.findGlobalVPNDevice(ctx, gvpnName, gv.KloudliteClusterLocalDevice.Name) - if err != nil { - return err - } - - wgParams, deviceHosts, err := d.buildGlobalVPNDeviceWgBaseParams(ctx, gvpnConns, klDevice) - if err != nil { - return err - } - - publicPeers := make([]wgutils.PublicPeer, 0, len(wgParams.PublicPeers)) - for _, p := range wgParams.PublicPeers { - if p.PublicKey != clDevice.PublicKey { - publicPeers = append(publicPeers, p) } } - deviceSvcHosts := make([]string, 0, len(deviceHosts)) - for k, v := range deviceHosts { - deviceSvcHosts = append(deviceSvcHosts, fmt.Sprintf("%s=%s", k, v)) - } - - wgParams.PublicPeers = publicPeers - wgParams.DNS = klDevice.IPAddr - wgParams.ListenPort = 31820 - - dnsServerArgs := make([]string, 0, len(gvpnConns)) - for _, gvpnConn := range gvpnConns { - if gvpnConn.Spec.GlobalIP != "" { - dnsServerArgs = append(dnsServerArgs, fmt.Sprintf("%s=%s:53", gvpnConn.Spec.DNSSuffix, gvpnConn.Spec.GlobalIP)) - } - } - - resourceName := fmt.Sprintf("kloudlite-device-%s", gv.Name) - resourceNamespace := accNs - selector := map[string]string{ - "app": resourceName, - } - - gao, err := d.accountsSvc.GetAccount(ctx, string(ctx.UserId), ctx.AccountName) - if err != nil { - return errors.NewE(err) - } - - gwRegion, ok := d.env.AvailableKloudliteRegions[gao.KloudliteGatewayRegion] - if !ok { - return errors.Newf("invalid gateway region %q", gao.KloudliteGatewayRegion) - } - wgEndpoint := gwRegion.PublicDNSHost - c, err := k8s.RestConfigFromKubeConfig([]byte(gwRegion.Kubeconfig)) - if err != nil { - return errors.NewE(err) - } - - yc, err := kubectl.NewYAMLClient(c, kubectl.YAMLClientOpts{}) + yc, err := kubectl.NewYAMLClient(k8sRestConfig, kubectl.YAMLClientOpts{}) if err != nil { return errors.NewE(err) } @@ -714,6 +543,11 @@ func (d *domain) syncKloudliteGatewayDevice2(ctx InfraContext, gvpnName string) return err } + b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) + if err != nil { + return errors.NewE(err) + } + deploymentBytes, err := templates.ParseBytes(b, templates.GVPNKloudliteDeviceTemplateVars{ Name: resourceName, Namespace: accNs, @@ -731,6 +565,7 @@ func (d *domain) syncKloudliteGatewayDevice2(ctx InfraContext, gvpnName string) return err } + d.logger.Info("applying yaml", "yaml", string(deploymentBytes)) if _, err := yc.ApplyYAML(ctx, deploymentBytes); err != nil { return errors.NewE(err) } @@ -745,12 +580,6 @@ syncKloudliteDeviceOnPlatform: - we can read their logs, and everything on demand */ func (d *domain) syncKloudliteDeviceOnPlatform(ctx InfraContext, gvpnName string) error { - // 1. parse deployment template - b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) - if err != nil { - return errors.NewE(err) - } - svcTemplate, err := templates.Read(templates.GatewayServiceTemplate) if err != nil { return errors.NewE(err) @@ -816,7 +645,8 @@ func (d *domain) syncKloudliteDeviceOnPlatform(ctx InfraContext, gvpnName string } } - resourceName := fmt.Sprintf("kloudlite-device-%s", gv.Name) + // resourceName := fmt.Sprintf("kloudlite-device-%s", gv.Name) + resourceName := fmt.Sprintf("device-%s-pl", gv.Name) resourceNamespace := accNs selector := map[string]string{ "app": resourceName, @@ -877,6 +707,11 @@ func (d *domain) syncKloudliteDeviceOnPlatform(ctx InfraContext, gvpnName string return err } + b, err := templates.Read(templates.GlobalVPNKloudliteDeviceTemplate) + if err != nil { + return errors.NewE(err) + } + deploymentBytes, err := templates.ParseBytes(b, templates.GVPNKloudliteDeviceTemplateVars{ Name: resourceName, Namespace: accNs, diff --git a/apps/infra/internal/domain/global-vpn-cluster-connection.go b/apps/infra/internal/domain/global-vpn-cluster-connection.go index 6b3a4935c..a4c7871d6 100644 --- a/apps/infra/internal/domain/global-vpn-cluster-connection.go +++ b/apps/infra/internal/domain/global-vpn-cluster-connection.go @@ -167,15 +167,18 @@ func (d *domain) reconGlobalVPNConnections(ctx InfraContext, vpnName string) err } xcc.Spec.Peers = peers - unp, err := d.gvpnConnRepo.Patch( - ctx, - repos.Filter{ - fields.AccountName: ctx.AccountName, - fields.ClusterName: xcc.ClusterName, - fields.MetadataName: xcc.Name, + unp, err := d.gvpnConnRepo.PatchById(ctx, xcc.Id, common.PatchForUpdate(ctx, xcc, common.PatchOpts{ + XPatch: map[string]any{ + fc.GlobalVPNConnectionSpecPeers: peers, }, - common.PatchForUpdate(ctx, xcc, common.PatchOpts{XPatch: map[string]any{fc.GlobalVPNConnectionSpecPeers: peers}}), - ) + })) + // unp, err := d.gvpnConnRepo.Patch(ctx, repos.Filter{ + // fields.AccountName: ctx.AccountName, + // fields.ClusterName: xcc.ClusterName, + // fields.MetadataName: xcc.Name, + // }, + // common.PatchForUpdate(ctx, xcc, common.PatchOpts{XPatch: map[string]any{fc.GlobalVPNConnectionSpecPeers: peers}}), + // ) if err != nil { return errors.NewE(err) } diff --git a/apps/infra/internal/domain/provider-secrets.go b/apps/infra/internal/domain/provider-secrets.go index e5f4e2386..bfa54e409 100644 --- a/apps/infra/internal/domain/provider-secrets.go +++ b/apps/infra/internal/domain/provider-secrets.go @@ -164,9 +164,6 @@ func (d *domain) CreateProviderSecret(ctx InfraContext, psecretIn entities.Cloud return nil, errors.NewE(err) } - if err != nil { - return nil, errors.NewE(err) - } if err := d.applyK8sResource(ctx, secret, nSecret.RecordVersion); err != nil { return nil, errors.NewE(err) } diff --git a/apps/infra/internal/env/env.go b/apps/infra/internal/env/env.go index ab93e31b1..110be4c41 100644 --- a/apps/infra/internal/env/env.go +++ b/apps/infra/internal/env/env.go @@ -9,7 +9,10 @@ import ( "sigs.k8s.io/yaml" ) -type Env struct { +type infraEnv struct { + IsDev bool + KubernetesApiProxy string `env:"KUBERNETES_API_PROXY" default:"http://localhost:8080"` + InfraDbUri string `env:"MONGO_DB_URI" required:"true"` InfraDbName string `env:"MONGO_DB_NAME" required:"true"` @@ -32,17 +35,7 @@ type Env struct { MessageOfficeInternalGrpcAddr string `env:"MESSAGE_OFFICE_INTERNAL_GRPC_ADDR" required:"true"` MessageOfficeExternalGrpcAddr string `env:"MESSAGE_OFFICE_EXTERNAL_GRPC_ADDR" required:"true"` - AWSCfParamTrustedARN string `env:"AWS_CF_PARAM_TRUSTED_ARN" required:"true"` - AWSCfStackNamePrefix string `env:"AWS_CF_STACK_NAME_PREFIX" required:"true"` - AWSCfRoleNamePrefix string `env:"AWS_CF_ROLE_NAME_PREFIX" required:"true"` - AWSCfInstanceProfileNamePrefix string `env:"AWS_CF_INSTANCE_PROFILE_NAME_PREFIX" required:"true"` - AWSCfStackS3URL string `env:"AWS_CF_STACK_S3_URL" required:"true"` - - AWSAccessKey string `env:"AWS_ACCESS_KEY" required:"true"` - AWSSecretKey string `env:"AWS_SECRET_KEY" required:"true"` - - PublicDNSHostSuffix string `env:"PUBLIC_DNS_HOST_SUFFIX" required:"true"` - SessionKVBucket string `env:"SESSION_KV_BUCKET" required:"true"` + SessionKVBucket string `env:"SESSION_KV_BUCKET" required:"true"` MsvcTemplateFilePath string `env:"MSVC_TEMPLATE_FILE_PATH" required:"true"` @@ -58,9 +51,6 @@ type Env struct { // ClusterOffset = 5, reserving 5 * 8K IPs for wireguard devices and other devices, that are not Clusters ClustersOffset int `env:"CLUSTERS_OFFSET" default:"5"` - IsDev bool - KubernetesApiProxy string `env:"KUBERNETES_API_PROXY"` - GlobalVPNKubeReverseProxyImage string `env:"GLOBAL_VPN_KUBE_REVERSE_PROXY_IMAGE" required:"true"` GlobalVPNKubeReverseProxyAuthzToken string `env:"GLOBAL_VPN_KUBE_REVERSE_PROXY_AUTHZ_TOKEN" required:"true"` @@ -68,6 +58,26 @@ type Env struct { AvailableKloudliteRegionsConfig string `env:"AVAILABLE_KLOUDLITE_REGIONS_CONFIG" required:"false"` AvailableKloudliteRegions map[string]AvailableKloudliteRegion + + EnableClusterCreation bool `env:"ENABLE_CLUSTER_CREATION" default:"false"` +} + +type Env struct { + clusterCreationEnv `json:",inline"` + infraEnv `json:",inline"` +} + +type clusterCreationEnv struct { + PublicDNSHostSuffix string `env:"PUBLIC_DNS_HOST_SUFFIX" required:"true"` + + AWSCfParamTrustedARN string `env:"AWS_CF_PARAM_TRUSTED_ARN" required:"true"` + AWSCfStackNamePrefix string `env:"AWS_CF_STACK_NAME_PREFIX" required:"true"` + AWSCfRoleNamePrefix string `env:"AWS_CF_ROLE_NAME_PREFIX" required:"true"` + AWSCfInstanceProfileNamePrefix string `env:"AWS_CF_INSTANCE_PROFILE_NAME_PREFIX" required:"true"` + AWSCfStackS3URL string `env:"AWS_CF_STACK_S3_URL" required:"true"` + + AWSAccessKey string `env:"AWS_ACCESS_KEY" required:"true"` + AWSSecretKey string `env:"AWS_SECRET_KEY" required:"true"` } type AvailableKloudliteRegion struct { @@ -81,9 +91,21 @@ type AvailableKloudliteRegion struct { func LoadEnv() (*Env, error) { var ev Env - if err := env.Set(&ev); err != nil { + + var iev infraEnv + if err := env.Set(&iev); err != nil { return nil, errors.NewE(err) } + ev.infraEnv = iev + + if iev.EnableClusterCreation { + var ccev clusterCreationEnv + if err := env.Set(&ccev); err != nil { + return nil, errors.NewE(err) + } + ev.clusterCreationEnv = ccev + } + if ev.AvailableKloudliteRegionsConfig != "" { f, err := os.Open(ev.AvailableKloudliteRegionsConfig) if err != nil { diff --git a/apps/infra/main.go b/apps/infra/main.go index d91ef0bd0..3648f26d9 100644 --- a/apps/infra/main.go +++ b/apps/infra/main.go @@ -61,7 +61,7 @@ func main() { }), fx.Provide(func(e *env.Env) (*rest.Config, error) { - if e.KubernetesApiProxy != "" { + if isDev && e.KubernetesApiProxy != "" { return &rest.Config{ Host: e.KubernetesApiProxy, }, nil From 45924f707737b1f656c3e3b143f73aa6d458b8b4 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Tue, 17 Sep 2024 17:32:30 +0530 Subject: [PATCH 14/17] feat(auth): supports enabling/disabling auth email verification This feature is useful while self-hosting the platform, as it saves initial hassle of setting up sendgrid and everything prior to installing chart itself. --- apps/auth/internal/app/app.go | 1 + .../internal/app/graph/schema.resolvers.go | 7 +++-- apps/auth/internal/domain/domain.go | 3 +- apps/auth/internal/domain/impl.go | 25 +++++++-------- apps/auth/internal/env/env.go | 2 ++ apps/auth/main.go | 31 ++++++++++++------- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/apps/auth/internal/app/app.go b/apps/auth/internal/app/app.go index 6a1efe60e..4080b8fe8 100644 --- a/apps/auth/internal/app/app.go +++ b/apps/auth/internal/app/app.go @@ -2,6 +2,7 @@ package app import ( "context" + "github.com/99designs/gqlgen/graphql" "github.com/gofiber/fiber/v2" "github.com/kloudlite/api/apps/auth/internal/app/graph" diff --git a/apps/auth/internal/app/graph/schema.resolvers.go b/apps/auth/internal/app/graph/schema.resolvers.go index e4f9cc636..709244229 100644 --- a/apps/auth/internal/app/graph/schema.resolvers.go +++ b/apps/auth/internal/app/graph/schema.resolvers.go @@ -6,6 +6,7 @@ package graph import ( "context" + "github.com/kloudlite/api/apps/auth/internal/app/graph/generated" "github.com/kloudlite/api/apps/auth/internal/app/graph/model" "github.com/kloudlite/api/common" @@ -285,5 +286,7 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } -type mutationResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } +type ( + mutationResolver struct{ *Resolver } + queryResolver struct{ *Resolver } +) diff --git a/apps/auth/internal/domain/domain.go b/apps/auth/internal/domain/domain.go index b752dd56a..54a317d20 100644 --- a/apps/auth/internal/domain/domain.go +++ b/apps/auth/internal/domain/domain.go @@ -2,6 +2,7 @@ package domain import ( "context" + "github.com/kloudlite/api/apps/auth/internal/entities" "github.com/kloudlite/api/common" "github.com/kloudlite/api/pkg/repos" @@ -38,7 +39,7 @@ type Domain interface { CreateInviteCode(ctx context.Context, name string, inviteCode string) (*entities.InviteCode, error) DeleteInviteCode(ctx context.Context, invCodeId string) error - //UpdateInviteCode(ctx context.Context, invCode entities.InviteCode) (*entities.InviteCode, error) + // UpdateInviteCode(ctx context.Context, invCode entities.InviteCode) (*entities.InviteCode, error) VerifyInviteCode(ctx context.Context, userId repos.ID, invitationCode string) (bool, error) } diff --git a/apps/auth/internal/domain/impl.go b/apps/auth/internal/domain/impl.go index 00af8d286..7e934a30c 100644 --- a/apps/auth/internal/domain/impl.go +++ b/apps/auth/internal/domain/impl.go @@ -7,11 +7,12 @@ import ( "encoding/hex" "encoding/json" "fmt" - "github.com/kloudlite/api/apps/auth/internal/entities" - "github.com/kloudlite/api/apps/auth/internal/env" "strings" "time" + "github.com/kloudlite/api/apps/auth/internal/entities" + "github.com/kloudlite/api/apps/auth/internal/env" + "github.com/kloudlite/api/constants" "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/comms" @@ -146,7 +147,6 @@ func (d *domainI) OauthAddLogin(ctx context.Context, userId repos.ID, provider s return false, errors.Newf("unknown provider=%s, aborting request", provider) } } - } func (d *domainI) GetUserById(ctx context.Context, id repos.ID) (*entities.User, error) { @@ -179,17 +179,14 @@ func (d *domainI) Login(ctx context.Context, email string, password string) (*co func (d *domainI) SignUp(ctx context.Context, name string, email string, password string) (*common.AuthSession, error) { matched, err := d.userRepo.FindOne(ctx, repos.Filter{"email": email}) - if err != nil { if matched != nil { return nil, errors.NewE(err) } } - if matched != nil { - if matched.Email == email { - return nil, errors.Newf("user(email=%s) already exists", email) - } + if matched != nil && matched.Email == email { + return nil, errors.Newf("user(email=%q) already exists", email) } salt := generateId("salt") @@ -199,21 +196,22 @@ func (d *domainI) SignUp(ctx context.Context, name string, email string, passwor Name: name, Email: email, Password: hex.EncodeToString(sum[:]), - Verified: false, + Verified: !d.envVars.UserEmailVerifactionEnabled, Approved: false, Metadata: nil, Joined: time.Now(), PasswordSalt: salt, }, ) - if err != nil { return nil, errors.NewE(err) } - err = d.generateAndSendVerificationToken(ctx, user) - if err != nil { - return nil, errors.NewE(err) + if d.envVars.UserEmailVerifactionEnabled { + err = d.generateAndSendVerificationToken(ctx, user) + if err != nil { + return nil, errors.NewE(err) + } } return newAuthSession(user.Id, user.Email, user.Name, user.Verified, "email/password"), nil @@ -437,7 +435,6 @@ func (d *domainI) addOAuthLogin(ctx context.Context, provider string, token *oau Token: token, }, ) - if err != nil { return nil, errors.NewEf(err, "could not store access token in repo") } diff --git a/apps/auth/internal/env/env.go b/apps/auth/internal/env/env.go index a009e28f4..8086e8ca9 100644 --- a/apps/auth/internal/env/env.go +++ b/apps/auth/internal/env/env.go @@ -14,6 +14,8 @@ type Env struct { CookieDomain string `env:"COOKIE_DOMAIN" required:"true"` + UserEmailVerifactionEnabled bool `env:"USER_EMAIL_VERIFICATION_ENABLED" default:"true"` + OAuth2Enabled bool `env:"OAUTH2_ENABLED" required:"true"` OAuth2GithubEnabled bool `env:"OAUTH2_GITHUB_ENABLED" required:"false"` diff --git a/apps/auth/main.go b/apps/auth/main.go index 944ed2adc..d9d5abf4f 100644 --- a/apps/auth/main.go +++ b/apps/auth/main.go @@ -3,7 +3,7 @@ package main import ( "context" "flag" - "log/slog" + "os" "time" "github.com/kloudlite/api/pkg/errors" @@ -18,9 +18,23 @@ import ( ) func main() { + common.PrintBuildInfo() + start := time.Now() + var isDev bool flag.BoolVar(&isDev, "dev", false, "--dev") + + var debug bool + flag.BoolVar(&debug, "debug", false, "--debug") + flag.Parse() + + if isDev { + debug = true + } + + logger := logging.NewSlogLogger(logging.SlogOptions{ShowCaller: true, ShowDebugLogs: debug, SetAsDefaultLogger: true}) + app := fx.New( fx.NopLogger, fn.FxErrorHandler(), @@ -38,29 +52,24 @@ func main() { }, ), - fx.Provide(func() *slog.Logger { - return logging.NewSlogLogger(logging.SlogOptions{ - ShowCaller: true, - ShowDebugLogs: isDev, - SetAsDefaultLogger: true, - }) - }), + fx.Supply(logger), framework.Module, ) ctx, cancelFunc := func() (context.Context, context.CancelFunc) { if isDev { - return context.WithTimeout(context.TODO(), 20*time.Second) + return context.WithTimeout(context.TODO(), 10*time.Second) } return context.WithTimeout(context.TODO(), 5*time.Second) }() defer cancelFunc() if err := app.Start(ctx); err != nil { - panic(err) + logger.Error("failed to start auth-api, got", "err", err) + os.Exit(1) } - common.PrintReadyBanner() + common.PrintReadyBanner2(time.Since(start)) <-app.Done() } From df918ed8755850f7a4276ee667784a8953e94fb3 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Tue, 17 Sep 2024 17:34:42 +0530 Subject: [PATCH 15/17] refactor(console): removes unused env vars --- apps/console/internal/env/env.go | 3 --- apps/console/main.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/console/internal/env/env.go b/apps/console/internal/env/env.go index 7e6582252..b119c4e5a 100644 --- a/apps/console/internal/env/env.go +++ b/apps/console/internal/env/env.go @@ -28,14 +28,11 @@ type Env struct { MessageOfficeInternalGRPCAddr string `env:"MESSAGE_OFFICE_INTERNAL_GRPC_ADDR" required:"true"` AccountGRPCAddr string `env:"ACCOUNT_GRPC_ADDR" required:"true"` - PromHttpAddr string `env:"PROM_HTTP_ADDR" required:"true"` SessionKVBucket string `env:"SESSION_KV_BUCKET" required:"true"` ConsoleCacheKVBucket string `env:"CONSOLE_CACHE_KV_BUCKET" required:"true"` IsDev bool KubernetesApiProxy string `env:"KUBERNETES_API_PROXY" default:"localhost:8080"` - - DeviceNamespace string `env:"DEVICE_NAMESPACE" required:"true"` } func LoadEnv() (*Env, error) { diff --git a/apps/console/main.go b/apps/console/main.go index 10fbee98d..ebf4dc4f5 100644 --- a/apps/console/main.go +++ b/apps/console/main.go @@ -54,7 +54,7 @@ func main() { }), fx.Provide(func(e *env.Env) (*rest.Config, error) { - if isDev && e.KubernetesApiProxy != "" { + if isDev { return &rest.Config{ Host: e.KubernetesApiProxy, }, nil From 6802a6b53c1ba8b86b6398cc173339905e389118 Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Tue, 17 Sep 2024 17:35:41 +0530 Subject: [PATCH 16/17] chore: message-office, tenant-agent and observability improvements --- .../__http__/accounts/accounts.graphql.yml | 5 +- .tools/nvim/__http__/console/apps.graphql.yml | 14 +- .../__http__/console/environments.graphql.yml | 16 +- .../internal/domain/environments/errors.go | 1 - .../internal/domain/environments/repo.go | 211 ------------------ .../internal/domain/environments/repo_test.go | 1 - .../internal/app/adapter-resource-apply.go | 2 - .../internal/framework/framework.go | 4 +- .../domain/platform-edge/repo_test.go | 1 + apps/observability/internal/app/app.go | 4 +- apps/tenant-agent/main.go | 7 +- .../internal/framework/framework.go | 5 +- apps/worker-audit-logging/main.go | 16 +- 13 files changed, 51 insertions(+), 236 deletions(-) delete mode 100644 apps/console/internal/domain/environments/errors.go delete mode 100644 apps/console/internal/domain/environments/repo.go delete mode 100644 apps/console/internal/domain/environments/repo_test.go diff --git a/.tools/nvim/__http__/accounts/accounts.graphql.yml b/.tools/nvim/__http__/accounts/accounts.graphql.yml index 72f09b06a..fc1c006d2 100644 --- a/.tools/nvim/__http__/accounts/accounts.graphql.yml +++ b/.tools/nvim/__http__/accounts/accounts.graphql.yml @@ -44,14 +44,15 @@ query: | accounts_createAccount(account: $account) { id isActive + kloudliteGatewayRegion } } variables: account: - contactEmail: "{{.email}}" - displayName: "Example Account Name" + displayName: "test account - nxt" metadata: name: "{{.accountName}}" + kloudliteGatewayRegion: "k3d/mt1" --- diff --git a/.tools/nvim/__http__/console/apps.graphql.yml b/.tools/nvim/__http__/console/apps.graphql.yml index 79296ef1e..8596d2df1 100644 --- a/.tools/nvim/__http__/console/apps.graphql.yml +++ b/.tools/nvim/__http__/console/apps.graphql.yml @@ -1,7 +1,7 @@ --- global: name: sample-app - envName: "test-env" + envName: "test-env5" --- label: List Apps @@ -85,7 +85,7 @@ variables: app: displayName: "sample app" metadata: - name: "{{.name}}" + name: "{{.name}}1" spec: services: - port: 80 @@ -145,3 +145,13 @@ variables: envName: "{{.envName}}" appName: "{{.name}}" --- + +label: Resync App +query: |+ + query Query($envName: String!, $name: String!) { + core_resyncApp(envName: $envName, name: $name) + } +variables: + envName: "{{.envName}}" + name: "{{.name}}" +--- diff --git a/.tools/nvim/__http__/console/environments.graphql.yml b/.tools/nvim/__http__/console/environments.graphql.yml index de567dc8f..d4694580e 100644 --- a/.tools/nvim/__http__/console/environments.graphql.yml +++ b/.tools/nvim/__http__/console/environments.graphql.yml @@ -1,7 +1,5 @@ --- -global: - envTargetNamespace: "nxtcoder17" - envName: "test-env" +global: {} --- label: List Environments @@ -41,6 +39,10 @@ query: |+ #graphql action } recordVersion + onlineStatus { + lastOnlineAt + willBeOfflineAt + } } } pageInfo { @@ -62,7 +64,7 @@ query: |+ #graphql apiVersion kind spec { - targetNamespace + targetNamespace } syncStatus { state @@ -78,9 +80,7 @@ variables: displayName: Display Name of a sample environment clusterName: "__kloudlite_enabled_cluster" metadata: - name: "{{.envName}}" - # spec: - # projectName: "{{.projectName}}" + name: "{{.envName}}8" --- label: resync environment @@ -125,7 +125,7 @@ query: |+ core_deleteEnvironment(envName: $envName) } variables: - envName: "{{.envName}}" + envName: "{{.envName}}4" --- --- diff --git a/apps/console/internal/domain/environments/errors.go b/apps/console/internal/domain/environments/errors.go deleted file mode 100644 index d4fcbc9f9..000000000 --- a/apps/console/internal/domain/environments/errors.go +++ /dev/null @@ -1 +0,0 @@ -package environments diff --git a/apps/console/internal/domain/environments/repo.go b/apps/console/internal/domain/environments/repo.go deleted file mode 100644 index e6a836be2..000000000 --- a/apps/console/internal/domain/environments/repo.go +++ /dev/null @@ -1,211 +0,0 @@ -package environments - -// import ( -// "fmt" -// "log/slog" -// "strings" -// -// "github.com/kloudlite/api/apps/console/internal/domain/ports" -// "github.com/kloudlite/api/apps/console/internal/domain/types" -// "github.com/kloudlite/api/apps/console/internal/entities" -// "github.com/kloudlite/api/common" -// "github.com/kloudlite/api/grpc-interfaces/kloudlite.io/rpc/iam" -// "github.com/kloudlite/api/pkg/errors" -// "github.com/kloudlite/api/pkg/k8s" -// "github.com/kloudlite/api/pkg/repos" -// -// iamT "github.com/kloudlite/api/apps/iam/types" -// t "github.com/kloudlite/api/pkg/types" -// crdsv1 "github.com/kloudlite/operator/apis/crds/v1" -// ) -// -// type Repo struct { -// logger *slog.Logger -// -// k8sClient k8s.Client -// environmentRepo repos.DbRepo[*entities.Environment] -// -// resourceEventPublisher types.ResourceEventPublisher -// -// iamSvc ports.IAMService -// } -// -// func getEnvironmentTargetNamespace(envName string) string { -// return fmt.Sprintf("env-%s", envName) -// } -// -// // ArchiveEnvironmentsForCluster implements Domain. -// func (r *Repo) ArchiveEnvironmentsForCluster(ctx types.ConsoleContext, clusterName string) (bool, error) { -// panic("unimplemented") -// } -// -// // CloneEnvironment implements Domain. -// func (r *Repo) CloneEnvironment(ctx types.ConsoleContext, args CloneEnvironmentArgs) (*entities.Environment, error) { -// panic("unimplemented") -// } -// -// // CreateEnvironment implements Domain. -// func (r *Repo) CreateEnvironment(ctx types.ConsoleContext, env entities.Environment) (*entities.Environment, error) { -// if strings.TrimSpace(env.ClusterName) == "" { -// return nil, errors.New("clustername must be set while creating environments") -// } -// -// env.EnsureGVK() -// if err := r.k8sClient.ValidateObject(ctx, &env.Environment); err != nil { -// return nil, errors.NewE(err) -// } -// -// env.IncrementRecordVersion() -// -// if env.Spec.TargetNamespace == "" { -// env.Spec.TargetNamespace = getEnvironmentTargetNamespace(env.Name) -// } -// -// if env.Spec.Routing == nil { -// env.Spec.Routing = &crdsv1.EnvironmentRouting{ -// Mode: crdsv1.EnvironmentRoutingModePrivate, -// } -// } -// -// env.CreatedBy = common.CreatedOrUpdatedBy{ -// UserId: ctx.UserId, -// UserName: ctx.UserName, -// UserEmail: ctx.UserEmail, -// } -// env.LastUpdatedBy = env.CreatedBy -// -// env.AccountName = ctx.AccountName -// env.SyncStatus = t.GenSyncStatus(t.SyncActionApply, env.RecordVersion) -// -// nenv, err := r.environmentRepo.Create(ctx, &env) -// if err != nil { -// if r.environmentRepo.ErrAlreadyExists(err) { -// // TODO: better insights into error, when it is being caused by duplicated indexes -// return nil, errors.NewE(err) -// } -// return nil, errors.NewE(err) -// } -// -// // FIXME: this should be setup when actually dispatching resource -// // if _, err := d.upsertEnvironmentResourceMapping(ResourceContext{ConsoleContext: ctx, EnvironmentName: env.Name}, &env); err != nil { -// // return nil, errors.NewE(err) -// // } -// -// r.resourceEventPublisher.PublishConsoleEvent(ctx, entities.ResourceTypeEnvironment, nenv.Name, types.PublishAdd) -// -// if _, err := r.iamSvc.AddMembership(ctx, &iam.AddMembershipIn{ -// UserId: string(ctx.UserId), -// ResourceType: string(iamT.ResourceEnvironment), -// ResourceRef: iamT.NewResourceRef(ctx.AccountName, iamT.ResourceEnvironment, nenv.Name), -// Role: string(iamT.RoleResourceOwner), -// }); err != nil { -// r.logger.Error("while adding membership, got", "err", err) -// } -// -// if err := d.applyEnvironmentTargetNamespace(ctx, nenv); err != nil { -// return nil, errors.NewE(err) -// } -// -// if err := d.applyK8sResource(ctx, nenv.Name, &nenv.Environment, nenv.RecordVersion); err != nil { -// return nil, errors.NewE(err) -// } -// -// if err := d.syncImagePullSecretsToEnvironment(ctx, nenv.Name); err != nil { -// return nil, errors.NewE(err) -// } -// -// return nenv, nil -// } -// -// // func (d *domain) CreateEnvironment(ctx ConsoleContext, env entities.Environment) (*entities.Environment, error) { -// // if strings.TrimSpace(env.ClusterName) == "" { -// // return nil, fmt.Errorf("clustername must be set while creating environments") -// // } -// // -// // env.EnsureGVK() -// // if err := d.k8sClient.ValidateObject(ctx, &env.Environment); err != nil { -// // return nil, errors.NewE(err) -// // } -// // -// // env.IncrementRecordVersion() -// // -// // if env.Spec.TargetNamespace == "" { -// // env.Spec.TargetNamespace = d.getEnvironmentTargetNamespace(env.Name) -// // } -// // -// // if env.Spec.Routing == nil { -// // env.Spec.Routing = &crdsv1.EnvironmentRouting{ -// // Mode: crdsv1.EnvironmentRoutingModePrivate, -// // } -// // } -// // -// // env.CreatedBy = common.CreatedOrUpdatedBy{ -// // UserId: ctx.UserId, -// // UserName: ctx.UserName, -// // UserEmail: ctx.UserEmail, -// // } -// // env.LastUpdatedBy = env.CreatedBy -// // -// // env.AccountName = ctx.AccountName -// // env.SyncStatus = t.GenSyncStatus(t.SyncActionApply, env.RecordVersion) -// // -// // nenv, err := d.environmentRepo.Create(ctx, &env) -// // if err != nil { -// // if d.environmentRepo.ErrAlreadyExists(err) { -// // // TODO: better insights into error, when it is being caused by duplicated indexes -// // return nil, errors.NewE(err) -// // } -// // return nil, errors.NewE(err) -// // } -// // -// // if _, err := d.upsertEnvironmentResourceMapping(ResourceContext{ConsoleContext: ctx, EnvironmentName: env.Name}, &env); err != nil { -// // return nil, errors.NewE(err) -// // } -// // -// // d.resourceEventPublisher.PublishConsoleEvent(ctx, entities.ResourceTypeEnvironment, nenv.Name, PublishAdd) -// // -// // if _, err := d.iamClient.AddMembership(ctx, &iam.AddMembershipIn{ -// // UserId: string(ctx.UserId), -// // ResourceType: string(iamT.ResourceEnvironment), -// // ResourceRef: iamT.NewResourceRef(ctx.AccountName, iamT.ResourceEnvironment, nenv.Name), -// // Role: string(iamT.RoleResourceOwner), -// // }); err != nil { -// // d.logger.Errorf(err, "error while adding membership") -// // } -// // -// // if err := d.applyEnvironmentTargetNamespace(ctx, nenv); err != nil { -// // return nil, errors.NewE(err) -// // } -// // -// // if err := d.applyK8sResource(ctx, nenv.Name, &nenv.Environment, nenv.RecordVersion); err != nil { -// // return nil, errors.NewE(err) -// // } -// // -// // if err := d.syncImagePullSecretsToEnvironment(ctx, nenv.Name); err != nil { -// // return nil, errors.NewE(err) -// // } -// // -// // return nenv, nil -// // } -// -// // DeleteEnvironment implements Domain. -// func (r *Repo) DeleteEnvironment(ctx types.ConsoleContext, name string) error { -// panic("unimplemented") -// } -// -// // GetEnvironment implements Domain. -// func (r *Repo) GetEnvironment(ctx types.ConsoleContext, name string) (*entities.Environment, error) { -// panic("unimplemented") -// } -// -// // ListEnvironments implements Domain. -// func (r *Repo) ListEnvironments(ctx types.ConsoleContext, search map[string]repos.MatchFilter, pq repos.CursorPagination) (*repos.PaginatedRecord[*entities.Environment], error) { -// panic("unimplemented") -// } -// -// // UpdateEnvironment implements Domain. -// func (r *Repo) UpdateEnvironment(ctx types.ConsoleContext, env entities.Environment) (*entities.Environment, error) { -// panic("unimplemented") -// } -// -// var _ Domain = (*Repo)(nil) diff --git a/apps/console/internal/domain/environments/repo_test.go b/apps/console/internal/domain/environments/repo_test.go deleted file mode 100644 index d4fcbc9f9..000000000 --- a/apps/console/internal/domain/environments/repo_test.go +++ /dev/null @@ -1 +0,0 @@ -package environments diff --git a/apps/container-registry/internal/app/adapter-resource-apply.go b/apps/container-registry/internal/app/adapter-resource-apply.go index e9defdefd..fa0247e32 100644 --- a/apps/container-registry/internal/app/adapter-resource-apply.go +++ b/apps/container-registry/internal/app/adapter-resource-apply.go @@ -43,7 +43,6 @@ func (a *resourceDispatcherImpl) ApplyToTargetCluster(ctx domain.RegistryContext b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.AccountName, - ClusterName: clusterName, Action: t.ActionApply, Object: m, }) @@ -67,7 +66,6 @@ func (d *resourceDispatcherImpl) DeleteFromTargetCluster(ctx domain.RegistryCont b, err := json.Marshal(t.AgentMessage{ AccountName: ctx.AccountName, - ClusterName: clusterName, Action: t.ActionDelete, Object: m, }) diff --git a/apps/iot-console/internal/framework/framework.go b/apps/iot-console/internal/framework/framework.go index b4daacb32..138dc2cd6 100644 --- a/apps/iot-console/internal/framework/framework.go +++ b/apps/iot-console/internal/framework/framework.go @@ -3,6 +3,8 @@ package framework import ( "context" "fmt" + "log/slog" + "github.com/kloudlite/api/apps/iot-console/internal/app" "github.com/kloudlite/api/apps/iot-console/internal/domain" "github.com/kloudlite/api/apps/iot-console/internal/env" @@ -32,7 +34,7 @@ var Module = fx.Module("framework", mongoDb.NewMongoClientFx[*fm](), - fx.Provide(func(ev *env.Env, logger logging.Logger) (*nats.Client, error) { + fx.Provide(func(ev *env.Env, logger *slog.Logger) (*nats.Client, error) { return nats.NewClient(ev.NatsURL, nats.ClientOpts{ Name: "console", Logger: logger, diff --git a/apps/message-office/internal/domain/platform-edge/repo_test.go b/apps/message-office/internal/domain/platform-edge/repo_test.go index a4c4ef4f7..a76a04c4b 100644 --- a/apps/message-office/internal/domain/platform-edge/repo_test.go +++ b/apps/message-office/internal/domain/platform-edge/repo_test.go @@ -172,6 +172,7 @@ func TestRepo_AllocatePlatformEdgeCluster(t *testing.T) { wantErr: mo_errors.ErrNoClustersInRegion, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { r := &Repo{ diff --git a/apps/observability/internal/app/app.go b/apps/observability/internal/app/app.go index 8741b1068..110eb18f9 100644 --- a/apps/observability/internal/app/app.go +++ b/apps/observability/internal/app/app.go @@ -118,7 +118,7 @@ var Module = fx.Module( } return k8s.NewClient(&rest.Config{ - Host: fmt.Sprintf("http://kloudlite-device-%s.kl-account-%s.svc.cluster.local:8080/clusters/%s", "default", accountName, clusterName), + Host: fmt.Sprintf("http://device-%s-pl.kl-%s.svc.cluster.local:8080/clusters/%s", "default", accountName, clusterName), WrapTransport: func(rt http.RoundTripper) http.RoundTripper { return httpServer.NewRoundTripperWithHeaders(rt, map[string][]string{ "X-Kloudlite-Authz": {fmt.Sprintf("Bearer %s", ev.GlobalVPNAuthzSecret)}, @@ -181,7 +181,7 @@ var Module = fx.Module( } return k8s.NewClient(&rest.Config{ - Host: fmt.Sprintf("http://kloudlite-device-%s.kl-account-%s.svc.cluster.local:8080/clusters/%s", "default", accountName, clusterName), + Host: fmt.Sprintf("http://device-%s-pl.kl-%s.svc.cluster.local:8080/clusters/%s", "default", accountName, clusterName), WrapTransport: func(rt http.RoundTripper) http.RoundTripper { return httpServer.NewRoundTripperWithHeaders(rt, map[string][]string{ "X-Kloudlite-Authz": {fmt.Sprintf("Bearer %s", ev.GlobalVPNAuthzSecret)}, diff --git a/apps/tenant-agent/main.go b/apps/tenant-agent/main.go index c0a9219b4..b75e08463 100644 --- a/apps/tenant-agent/main.go +++ b/apps/tenant-agent/main.go @@ -76,15 +76,16 @@ func NewAuthorizedGrpcContext(ctx context.Context, accessToken string) context.C return metadata.NewOutgoingContext(ctx, metadata.Pairs("authorization", accessToken)) } -func (g *grpcHandler) handleMessage(gctx context.Context, msg t.AgentMessage) error { +func (g *grpcHandler) handleMessage(_ context.Context, msg t.AgentMessage) error { g.incrementCounter() start := time.Now() + logger := g.logger.With("counter", g.inMemCounter, "account", msg.AccountName, "action", msg.Action) ctx, cf := func() (context.Context, context.CancelFunc) { if g.isDev { - return context.WithCancel(gctx) + return context.WithCancel(context.TODO()) } - return context.WithTimeout(gctx, 3*time.Second) + return context.WithTimeout(context.TODO(), 2*time.Second) }() defer cf() diff --git a/apps/worker-audit-logging/internal/framework/framework.go b/apps/worker-audit-logging/internal/framework/framework.go index f667dc202..a55017552 100644 --- a/apps/worker-audit-logging/internal/framework/framework.go +++ b/apps/worker-audit-logging/internal/framework/framework.go @@ -1,10 +1,11 @@ package framework import ( + "log/slog" + "github.com/kloudlite/api/apps/worker-audit-logging/internal/app" "github.com/kloudlite/api/apps/worker-audit-logging/internal/env" "github.com/kloudlite/api/pkg/errors" - "github.com/kloudlite/api/pkg/logging" "github.com/kloudlite/api/pkg/nats" repos "github.com/kloudlite/api/pkg/repos" "go.uber.org/fx" @@ -27,7 +28,7 @@ var Module fx.Option = fx.Module("framework", return &redpandaCfg{ev: ev} }), - fx.Provide(func(ev *env.Env, logger logging.Logger) (*nats.JetstreamClient, error) { + fx.Provide(func(ev *env.Env, logger *slog.Logger) (*nats.JetstreamClient, error) { name := "audit-worker:jetstream-client" nc, err := nats.NewClient(ev.NatsURL, nats.ClientOpts{ Name: name, diff --git a/apps/worker-audit-logging/main.go b/apps/worker-audit-logging/main.go index b62561146..cdfad30b2 100644 --- a/apps/worker-audit-logging/main.go +++ b/apps/worker-audit-logging/main.go @@ -4,21 +4,33 @@ import ( "context" "flag" "fmt" + "time" + "github.com/kloudlite/api/apps/worker-audit-logging/internal/env" "github.com/kloudlite/api/apps/worker-audit-logging/internal/framework" "github.com/kloudlite/api/pkg/config" fn "github.com/kloudlite/api/pkg/functions" "github.com/kloudlite/api/pkg/logging" "go.uber.org/fx" - "time" ) func main() { var isDev bool flag.BoolVar(&isDev, "dev", false, "--dev") + + var debug bool + flag.BoolVar(&debug, "debug", false, "--debug") + flag.Parse() + logger := logging.NewSlogLogger(logging.SlogOptions{ + ShowCaller: true, + ShowDebugLogs: debug, + SetAsDefaultLogger: true, + }) + app := fx.New( + fx.NopLogger, func() fx.Option { if isDev { return fx.Options() @@ -30,6 +42,8 @@ func main() { return logging.New(&logging.Options{Name: "audit-logging-worker", Dev: isDev}) }, ), + fx.Supply(logger), + fn.FxErrorHandler(), config.EnvFx[env.Env](), framework.Module, From d5c1324f2875702ea017570be55a7163490a262c Mon Sep 17 00:00:00 2001 From: nxtcoder17 Date: Tue, 17 Sep 2024 18:22:25 +0530 Subject: [PATCH 17/17] chore: updates github.com/kloudlite/operator --- .../container-registry/internal/app/process-error-on-apply.go | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/container-registry/internal/app/process-error-on-apply.go b/apps/container-registry/internal/app/process-error-on-apply.go index 36ba29c7e..fa23b52f6 100644 --- a/apps/container-registry/internal/app/process-error-on-apply.go +++ b/apps/container-registry/internal/app/process-error-on-apply.go @@ -36,8 +36,8 @@ func ProcessErrorOnApply(consumer ErrorOnApplyConsumer, logger logging.Logger, d mLogger := logger.WithKV( "gvk", obj.GroupVersionKind(), - "accountName", errMsg.AccountName, - "clusterName", errMsg.ClusterName, + "accountName", em.AccountName, + "clusterName", em.ClusterName, ) mLogger.Infof("[%d] received message", counter) diff --git a/go.mod b/go.mod index ce261d87b..8c2e56cb3 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/google/go-github/v43 v43.0.0 github.com/google/go-github/v45 v45.2.0 github.com/gorilla/websocket v1.5.0 - github.com/kloudlite/operator v0.0.0-20240828110352-a9cc09ec2511 + github.com/kloudlite/operator v0.0.0-20240917124613-0418df6214cf github.com/matoous/go-nanoid/v2 v2.0.0 github.com/pkg/errors v0.9.1 github.com/sendgrid/sendgrid-go v3.11.1+incompatible diff --git a/go.sum b/go.sum index 5a3647830..440a7dcd0 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,8 @@ github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2 github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kloudlite/container-registry-authorizer v0.0.0-20231021122509-161dc30fde55 h1:YnZh3TL6AG4EfoInx1/L5zcPHd2QxgLKseJB1KtHjdQ= github.com/kloudlite/container-registry-authorizer v0.0.0-20231021122509-161dc30fde55/go.mod h1:GZj3wZmIw/qCciclRhgQTgmGiqe8wxoVzMXQjbOfnbc= -github.com/kloudlite/operator v0.0.0-20240828110352-a9cc09ec2511 h1:6+Dt7TsoCI9U0UIk6BNxdFCB2YZ4nkjBqSrG3qoyGdw= -github.com/kloudlite/operator v0.0.0-20240828110352-a9cc09ec2511/go.mod h1:VkreINDW43qeTsDv9gfGH5M9c5OG/jPGYOGxj8otsGY= +github.com/kloudlite/operator v0.0.0-20240917124613-0418df6214cf h1:GPPzhVCddW5Ba+gxaumhdX3cq5HB6qs99v47v2aKbkc= +github.com/kloudlite/operator v0.0.0-20240917124613-0418df6214cf/go.mod h1:VkreINDW43qeTsDv9gfGH5M9c5OG/jPGYOGxj8otsGY= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=