diff --git a/apps/console/internal/app/graph/generated/generated.go b/apps/console/internal/app/graph/generated/generated.go index 5f70958c9..e4b0b840f 100644 --- a/apps/console/internal/app/graph/generated/generated.go +++ b/apps/console/internal/app/graph/generated/generated.go @@ -762,6 +762,7 @@ type ComplexityRoot struct { CoreDeleteSecret func(childComplexity int, envName string, secretName string) int CoreImportManagedResource func(childComplexity int, envName string, msvcName string, mresName string, importName string) int CoreInterceptApp func(childComplexity int, envName string, appname string, deviceName string, intercept bool, portMappings []*v1.AppInterceptPortMappings) int + CoreInterceptAppOnLocalCluster func(childComplexity int, envName string, appname string, clusterName string, ipAddr string, intercept bool, portMappings []*v1.AppInterceptPortMappings) int CoreInterceptExternalApp func(childComplexity int, envName string, externalAppName string, deviceName string, intercept bool, portMappings []*v1.AppInterceptPortMappings) int CoreRemoveDeviceIntercepts func(childComplexity int, envName string, deviceName string) int CoreUpdateApp func(childComplexity int, envName string, app entities.App) int @@ -1081,6 +1082,7 @@ type MutationResolver interface { CoreUpdateApp(ctx context.Context, envName string, app entities.App) (*entities.App, error) CoreDeleteApp(ctx context.Context, envName string, appName string) (bool, error) CoreInterceptApp(ctx context.Context, envName string, appname string, deviceName string, intercept bool, portMappings []*v1.AppInterceptPortMappings) (bool, error) + CoreInterceptAppOnLocalCluster(ctx context.Context, envName string, appname string, clusterName string, ipAddr string, intercept bool, portMappings []*v1.AppInterceptPortMappings) (bool, error) CoreRemoveDeviceIntercepts(ctx context.Context, envName string, deviceName string) (bool, error) CoreCreateExternalApp(ctx context.Context, envName string, externalApp entities.ExternalApp) (*entities.ExternalApp, error) CoreUpdateExternalApp(ctx context.Context, envName string, externalApp entities.ExternalApp) (*entities.ExternalApp, error) @@ -4380,6 +4382,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CoreInterceptApp(childComplexity, args["envName"].(string), args["appname"].(string), args["deviceName"].(string), args["intercept"].(bool), args["portMappings"].([]*v1.AppInterceptPortMappings)), true + case "Mutation.core_interceptAppOnLocalCluster": + if e.complexity.Mutation.CoreInterceptAppOnLocalCluster == nil { + break + } + + args, err := ec.field_Mutation_core_interceptAppOnLocalCluster_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CoreInterceptAppOnLocalCluster(childComplexity, args["envName"].(string), args["appname"].(string), args["clusterName"].(string), args["ipAddr"].(string), args["intercept"].(bool), args["portMappings"].([]*v1.AppInterceptPortMappings)), true + case "Mutation.core_interceptExternalApp": if e.complexity.Mutation.CoreInterceptExternalApp == nil { break @@ -6005,6 +6019,7 @@ type Mutation { core_updateApp(envName: String!, app: AppIn!): App @isLoggedInAndVerified @hasAccount core_deleteApp(envName: String!, appName: String!): Boolean! @isLoggedInAndVerified @hasAccount core_interceptApp(envName: String!, appname: String!, deviceName: String!, intercept: Boolean!, portMappings: [Github__com___kloudlite___operator___apis___crds___v1__AppInterceptPortMappingsIn!]): Boolean! @isLoggedInAndVerified @hasAccount + core_interceptAppOnLocalCluster(envName: String!, appname: String!, clusterName: String!, ipAddr: String!, intercept: Boolean!, portMappings: [Github__com___kloudlite___operator___apis___crds___v1__AppInterceptPortMappingsIn!]): Boolean! @isLoggedInAndVerified @hasAccount core_removeDeviceIntercepts(envName: String!, deviceName: String!): Boolean! @isLoggedInAndVerified @hasAccount core_createExternalApp(envName: String!, externalApp: ExternalAppIn!): ExternalApp @isLoggedInAndVerified @hasAccount @@ -8024,6 +8039,66 @@ func (ec *executionContext) field_Mutation_core_importManagedResource_args(ctx c return args, nil } +func (ec *executionContext) field_Mutation_core_interceptAppOnLocalCluster_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["envName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("envName")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["envName"] = arg0 + var arg1 string + if tmp, ok := rawArgs["appname"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("appname")) + arg1, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["appname"] = arg1 + var arg2 string + if tmp, ok := rawArgs["clusterName"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("clusterName")) + arg2, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["clusterName"] = arg2 + var arg3 string + if tmp, ok := rawArgs["ipAddr"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ipAddr")) + arg3, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ipAddr"] = arg3 + var arg4 bool + if tmp, ok := rawArgs["intercept"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("intercept")) + arg4, err = ec.unmarshalNBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["intercept"] = arg4 + var arg5 []*v1.AppInterceptPortMappings + if tmp, ok := rawArgs["portMappings"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("portMappings")) + arg5, err = ec.unmarshalOGithub__com___kloudlite___operator___apis___crds___v1__AppInterceptPortMappingsIn2ᚕᚖgithubᚗcomᚋkloudliteᚋoperatorᚋapisᚋcrdsᚋv1ᚐAppInterceptPortMappingsᚄ(ctx, tmp) + if err != nil { + return nil, err + } + } + args["portMappings"] = arg5 + return args, nil +} + func (ec *executionContext) field_Mutation_core_interceptApp_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -29559,6 +29634,87 @@ func (ec *executionContext) fieldContext_Mutation_core_interceptApp(ctx context. return fc, nil } +func (ec *executionContext) _Mutation_core_interceptAppOnLocalCluster(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_core_interceptAppOnLocalCluster(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) { + directive0 := func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CoreInterceptAppOnLocalCluster(rctx, fc.Args["envName"].(string), fc.Args["appname"].(string), fc.Args["clusterName"].(string), fc.Args["ipAddr"].(string), fc.Args["intercept"].(bool), fc.Args["portMappings"].([]*v1.AppInterceptPortMappings)) + } + directive1 := func(ctx context.Context) (interface{}, error) { + if ec.directives.IsLoggedInAndVerified == nil { + return nil, errors.New("directive isLoggedInAndVerified is not implemented") + } + return ec.directives.IsLoggedInAndVerified(ctx, nil, directive0) + } + directive2 := func(ctx context.Context) (interface{}, error) { + if ec.directives.HasAccount == nil { + return nil, errors.New("directive hasAccount is not implemented") + } + return ec.directives.HasAccount(ctx, nil, directive1) + } + + tmp, err := directive2(rctx) + if err != nil { + return nil, graphql.ErrorOnPath(ctx, err) + } + if tmp == nil { + return nil, nil + } + if data, ok := tmp.(bool); ok { + return data, nil + } + return nil, fmt.Errorf(`unexpected type %T from directive, should be bool`, tmp) + }) + 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.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_core_interceptAppOnLocalCluster(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_core_interceptAppOnLocalCluster_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_core_removeDeviceIntercepts(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_core_removeDeviceIntercepts(ctx, field) if err != nil { @@ -51350,6 +51506,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "core_interceptAppOnLocalCluster": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_core_interceptAppOnLocalCluster(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "core_removeDeviceIntercepts": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_core_removeDeviceIntercepts(ctx, field) diff --git a/apps/console/internal/app/graph/schema.graphqls b/apps/console/internal/app/graph/schema.graphqls index 1574c875b..d509fa652 100644 --- a/apps/console/internal/app/graph/schema.graphqls +++ b/apps/console/internal/app/graph/schema.graphqls @@ -175,6 +175,7 @@ type Mutation { core_updateApp(envName: String!, app: AppIn!): App @isLoggedInAndVerified @hasAccount core_deleteApp(envName: String!, appName: String!): Boolean! @isLoggedInAndVerified @hasAccount core_interceptApp(envName: String!, appname: String!, deviceName: String!, intercept: Boolean!, portMappings: [Github__com___kloudlite___operator___apis___crds___v1__AppInterceptPortMappingsIn!]): Boolean! @isLoggedInAndVerified @hasAccount + core_interceptAppOnLocalCluster(envName: String!, appname: String!, clusterName: String!, ipAddr: String!, intercept: Boolean!, portMappings: [Github__com___kloudlite___operator___apis___crds___v1__AppInterceptPortMappingsIn!]): Boolean! @isLoggedInAndVerified @hasAccount core_removeDeviceIntercepts(envName: String!, deviceName: String!): Boolean! @isLoggedInAndVerified @hasAccount core_createExternalApp(envName: String!, externalApp: ExternalAppIn!): ExternalApp @isLoggedInAndVerified @hasAccount diff --git a/apps/console/internal/app/graph/schema.resolvers.go b/apps/console/internal/app/graph/schema.resolvers.go index fa37b21a7..ef08ea747 100644 --- a/apps/console/internal/app/graph/schema.resolvers.go +++ b/apps/console/internal/app/graph/schema.resolvers.go @@ -207,6 +207,23 @@ func (r *mutationResolver) CoreInterceptApp(ctx context.Context, envName string, return r.Domain.InterceptApp(newResourceContext(cc, envName), appname, deviceName, intercept, pmappings) } +// CoreInterceptAppOnLocalCluster is the resolver for the core_interceptAppOnLocalCluster field. +func (r *mutationResolver) CoreInterceptAppOnLocalCluster(ctx context.Context, envName string, appname string, clusterName string, ipAddr string, intercept bool, portMappings []*v11.AppInterceptPortMappings) (bool, error) { + cc, err := toConsoleContext(ctx) + if err != nil { + return false, errors.NewE(err) + } + + pmappings := make([]v11.AppInterceptPortMappings, 0, len(portMappings)) + for i := range portMappings { + if portMappings[i] != nil { + pmappings = append(pmappings, *portMappings[i]) + } + } + + return r.Domain.InterceptAppOnLocalCluster(newResourceContext(cc, envName), appname, clusterName, ipAddr, intercept, pmappings) +} + // CoreRemoveDeviceIntercepts is the resolver for the core_removeDeviceIntercepts field. func (r *mutationResolver) CoreRemoveDeviceIntercepts(ctx context.Context, envName string, deviceName string) (bool, error) { cc, err := toConsoleContext(ctx) diff --git a/apps/console/internal/domain/api.go b/apps/console/internal/domain/api.go index 2c50d6065..601b6c2b7 100644 --- a/apps/console/internal/domain/api.go +++ b/apps/console/internal/domain/api.go @@ -195,6 +195,7 @@ type Domain interface { DeleteApp(ctx ResourceContext, name string) error InterceptApp(ctx ResourceContext, appName string, deviceName string, intercept bool, portMappings []crdsv1.AppInterceptPortMappings) (bool, error) + InterceptAppOnLocalCluster(ctx ResourceContext, appName string, clusterName string, ipAddr string, intercept bool, portMappings []crdsv1.AppInterceptPortMappings) (bool, error) RestartApp(ctx ResourceContext, appName string) error RemoveDeviceIntercepts(ctx ResourceContext, deviceName string) error diff --git a/apps/console/internal/domain/app.go b/apps/console/internal/domain/app.go index db23bca45..65d02086b 100644 --- a/apps/console/internal/domain/app.go +++ b/apps/console/internal/domain/app.go @@ -233,6 +233,32 @@ func (d *domain) InterceptApp(ctx ResourceContext, appName string, deviceName st return true, nil } +// InterceptApp implements Domain. +func (d *domain) InterceptAppOnLocalCluster(ctx ResourceContext, appName string, clusterName string, ipAddr string, intercept bool, portMappings []crdsv1.AppInterceptPortMappings) (bool, error) { + if err := d.canMutateResourcesInEnvironment(ctx); err != nil { + return false, errors.NewE(err) + } + + patch := repos.Document{ + fc.AppSpecInterceptEnabled: intercept, + fc.AppSpecInterceptToDevice: clusterName, + fc.AppSpecInterceptToIPAddr: ipAddr, + } + + if portMappings != nil { + patch[fc.AppSpecInterceptPortMappings] = portMappings + } + + uApp, err := d.appRepo.Patch(ctx, ctx.DBFilters().Add(fields.MetadataName, appName), patch) + if err != nil { + return false, errors.NewE(err) + } + if err := d.applyApp(ctx, uApp); err != nil { + return false, errors.NewE(err) + } + return true, nil +} + func (d *domain) RestartApp(ctx ResourceContext, appName string) error { if err := d.canMutateResourcesInEnvironment(ctx); err != nil { return errors.NewE(err) diff --git a/apps/console/internal/entities/field-constants/generated_constants.go b/apps/console/internal/entities/field-constants/generated_constants.go index b31327d13..ba396a632 100644 --- a/apps/console/internal/entities/field-constants/generated_constants.go +++ b/apps/console/internal/entities/field-constants/generated_constants.go @@ -21,6 +21,7 @@ const ( AppSpecInterceptEnabled = "spec.intercept.enabled" AppSpecInterceptPortMappings = "spec.intercept.portMappings" AppSpecInterceptToDevice = "spec.intercept.toDevice" + AppSpecInterceptToIPAddr = "spec.intercept.toIPAddr" AppSpecNodeSelector = "spec.nodeSelector" AppSpecRegion = "spec.region" AppSpecReplicas = "spec.replicas" @@ -122,6 +123,7 @@ const ( ExternalAppSpecInterceptEnabled = "spec.intercept.enabled" ExternalAppSpecInterceptPortMappings = "spec.intercept.portMappings" ExternalAppSpecInterceptToDevice = "spec.intercept.toDevice" + ExternalAppSpecInterceptToIPAddr = "spec.intercept.toIPAddr" ExternalAppSpecRecord = "spec.record" ExternalAppSpecRecordType = "spec.recordType" ) diff --git a/go.mod b/go.mod index 953d3f2c9..b39e27ea2 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-20240924122932-030f95a15613 + github.com/kloudlite/operator v0.0.0-20240927061728-c8cb9559e4c3 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 8bf458a03..35ae5f098 100644 --- a/go.sum +++ b/go.sum @@ -179,8 +179,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-20240924122932-030f95a15613 h1:2vmIyEscCnsRpZ0zaXov1jglR+UcRnCwa4va7DbwcYc= -github.com/kloudlite/operator v0.0.0-20240924122932-030f95a15613/go.mod h1:VkreINDW43qeTsDv9gfGH5M9c5OG/jPGYOGxj8otsGY= +github.com/kloudlite/operator v0.0.0-20240927061728-c8cb9559e4c3 h1:7FaI5EE5oxaf10qVhunIrh2p9cf2U1e7AzarfzDuKtQ= +github.com/kloudlite/operator v0.0.0-20240927061728-c8cb9559e4c3/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=