From 5b309353f2c1b39991a5a72eecd075fcf83ca7c9 Mon Sep 17 00:00:00 2001 From: Thomas Krampl Date: Thu, 17 Oct 2024 13:33:56 +0200 Subject: [PATCH] Add instances to application --- .../simple/dev/slug-1/another.yaml | 19 + .../k8s_resources/simple/dev/slug-1/app.yaml | 27 + integration_tests/team_applications.lua | 77 + internal/v1/graphv1/applications.resolvers.go | 21 + internal/v1/graphv1/gengqlv1/generated.go | 1625 +++++++++++++++-- .../v1/graphv1/schema/applications.graphqls | 53 +- .../v1/status/check_no_running_instances.go | 2 +- internal/v1/workload/application/models.go | 65 +- internal/v1/workload/application/node.go | 15 + internal/v1/workload/application/queries.go | 28 +- internal/v1/workload/queries.go | 6 +- 11 files changed, 1805 insertions(+), 133 deletions(-) diff --git a/integration_tests/k8s_resources/simple/dev/slug-1/another.yaml b/integration_tests/k8s_resources/simple/dev/slug-1/another.yaml index 740ad4e01..d0e20a82b 100644 --- a/integration_tests/k8s_resources/simple/dev/slug-1/another.yaml +++ b/integration_tests/k8s_resources/simple/dev/slug-1/another.yaml @@ -28,3 +28,22 @@ spec: name: app-name port: number: 80 + +--- +apiVersion: v1 +kind: Pod +metadata: + name: another-app-23422-2sdf + labels: + app: another-app + creationTimestamp: "2022-07-06T09:45:18Z" +spec: + containers: + - name: another-app + image: navikt/app-name:latest + resources: + limits: + memory: "128Mi" + cpu: "500m" + ports: + - containerPort: 80 diff --git a/integration_tests/k8s_resources/simple/dev/slug-1/app.yaml b/integration_tests/k8s_resources/simple/dev/slug-1/app.yaml index 6a7848376..be3be2baa 100644 --- a/integration_tests/k8s_resources/simple/dev/slug-1/app.yaml +++ b/integration_tests/k8s_resources/simple/dev/slug-1/app.yaml @@ -28,3 +28,30 @@ spec: name: my-app port: number: 80 + +--- +apiVersion: v1 +kind: Pod +metadata: + name: app-name-23422-2sdf + labels: + app: app-name + creationTimestamp: "2022-07-06T09:45:18Z" +spec: + containers: + - name: app-name + image: navikt/app-name:latest + resources: + limits: + memory: "128Mi" + cpu: "500m" + ports: + - containerPort: 80 +status: + containerStatuses: + - name: app-name + ready: true + restartCount: 0 + state: + running: + startedAt: "2022-07-06T09:45:18Z" diff --git a/integration_tests/team_applications.lua b/integration_tests/team_applications.lua index f65c02a57..2dafabf53 100644 --- a/integration_tests/team_applications.lua +++ b/integration_tests/team_applications.lua @@ -96,3 +96,80 @@ Test.gql("Team with no applications", function(t) } } end) + +Test.gql("Team with multiple applications and instances", function(t) + t.query [[ + query { + team(slug: "slug-1") { + applications { + nodes { + name + instances { + nodes { + name + id + restarts + created + status { + state + message + } + } + } + } + pageInfo { + totalCount + } + } + } + } + ]] + + t.check { + data = { + team = { + applications = { + nodes = { + { + name = "another-app", + instances = { + nodes = { + { + created = "2022-07-06T11:45:18+02:00", + id = "INS_3reJsVY19Sss8MvJH7ghHt6WcbXHW4AqMH7QPYi5yvJr6qZLw936mCi2ZcD9eM", + name = "another-app-23422-2sdf", + restarts = 0, + status = { + message = "Unknown", + state = "UNKNOWN" + }, + } + } + }, + }, + { + name = "app-name", + instances = { + nodes = { + { + created = "2022-07-06T11:45:18+02:00", + id = "INS_2JN3xdYkjgBWnSYwiqQiRZV44TR5uGVaoEkRVTyLhY53YfVFGju1k9", + name = "app-name-23422-2sdf", + restarts = 0, + status = { + message = "Running", + state = "RUNNING" + }, + } + } + }, + } + }, + pageInfo = { + totalCount = 2 + } + } + } + } + } +end) diff --git a/internal/v1/graphv1/applications.resolvers.go b/internal/v1/graphv1/applications.resolvers.go index e5ec2a766..c9a59d3dc 100644 --- a/internal/v1/graphv1/applications.resolvers.go +++ b/internal/v1/graphv1/applications.resolvers.go @@ -46,6 +46,14 @@ func (r *applicationResolver) Manifest(ctx context.Context, obj *application.App return application.Manifest(ctx, obj.TeamSlug, obj.EnvironmentName, obj.Name) } +func (r *applicationResolver) Instances(ctx context.Context, obj *application.Application, first *int, after *pagination.Cursor, last *int, before *pagination.Cursor) (*pagination.Connection[*application.Instance], error) { + page, err := pagination.ParsePage(first, after, last, before) + if err != nil { + return nil, err + } + return application.ListInstances(ctx, obj.TeamSlug, obj.EnvironmentName, obj.Name, page) +} + func (r *deleteApplicationPayloadResolver) Team(ctx context.Context, obj *application.DeleteApplicationPayload) (*team.Team, error) { if obj.TeamSlug == nil { return nil, nil @@ -133,3 +141,16 @@ type ( ingressResolver struct{ *Resolver } restartApplicationPayloadResolver struct{ *Resolver } ) + +// !!! WARNING !!! +// The code below was going to be deleted when updating resolvers. It has been copied here so you have +// one last chance to move it out of harms way if you want. There are two reasons this happens: +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. +/* + func (r *instanceResolver) Status(ctx context.Context, obj *application.Instance) (*application.InstanceStatus, error) { + panic(fmt.Errorf("not implemented: Status - status")) +} +func (r *Resolver) Instance() gengqlv1.InstanceResolver { return &instanceResolver{r} } +*/ diff --git a/internal/v1/graphv1/gengqlv1/generated.go b/internal/v1/graphv1/gengqlv1/generated.go index e50759715..7848205da 100644 --- a/internal/v1/graphv1/gengqlv1/generated.go +++ b/internal/v1/graphv1/gengqlv1/generated.go @@ -132,6 +132,7 @@ type ComplexityRoot struct { ID func(childComplexity int) int Image func(childComplexity int) int Ingresses func(childComplexity int) int + Instances func(childComplexity int, first *int, after *pagination.Cursor, last *int, before *pagination.Cursor) int KafkaTopicAcls func(childComplexity int, orderBy *kafkatopic.KafkaTopicACLOrder) int Manifest func(childComplexity int) int Name func(childComplexity int) int @@ -370,6 +371,31 @@ type ComplexityRoot struct { URL func(childComplexity int) int } + Instance struct { + Created func(childComplexity int) int + ID func(childComplexity int) int + Image func(childComplexity int) int + Name func(childComplexity int) int + Restarts func(childComplexity int) int + Status func(childComplexity int) int + } + + InstanceConnection struct { + Edges func(childComplexity int) int + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + InstanceEdge struct { + Cursor func(childComplexity int) int + Node func(childComplexity int) int + } + + InstanceStatus struct { + Message func(childComplexity int) int + State func(childComplexity int) int + } + Job struct { AuthIntegrations func(childComplexity int) int BigQueryDatasets func(childComplexity int, orderBy *bigquery.BigQueryDatasetOrder) int @@ -1359,6 +1385,7 @@ type ApplicationResolver interface { AuthIntegrations(ctx context.Context, obj *application.Application) ([]workload.ApplicationAuthIntegrations, error) Manifest(ctx context.Context, obj *application.Application) (*application.ApplicationManifest, error) + Instances(ctx context.Context, obj *application.Application, first *int, after *pagination.Cursor, last *int, before *pagination.Cursor) (*pagination.Connection[*application.Instance], error) BigQueryDatasets(ctx context.Context, obj *application.Application, orderBy *bigquery.BigQueryDatasetOrder) (*pagination.Connection[*bigquery.BigQueryDataset], error) Buckets(ctx context.Context, obj *application.Application, orderBy *bucket.BucketOrder) (*pagination.Connection[*bucket.Bucket], error) Cost(ctx context.Context, obj *application.Application) (*cost.WorkloadCost, error) @@ -1729,6 +1756,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Application.Ingresses(childComplexity), true + case "Application.instances": + if e.complexity.Application.Instances == nil { + break + } + + args, err := ec.field_Application_instances_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Application.Instances(childComplexity, args["first"].(*int), args["after"].(*pagination.Cursor), args["last"].(*int), args["before"].(*pagination.Cursor)), true + case "Application.kafkaTopicAcls": if e.complexity.Application.KafkaTopicAcls == nil { break @@ -2571,6 +2610,97 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Ingress.URL(childComplexity), true + case "Instance.created": + if e.complexity.Instance.Created == nil { + break + } + + return e.complexity.Instance.Created(childComplexity), true + + case "Instance.id": + if e.complexity.Instance.ID == nil { + break + } + + return e.complexity.Instance.ID(childComplexity), true + + case "Instance.image": + if e.complexity.Instance.Image == nil { + break + } + + return e.complexity.Instance.Image(childComplexity), true + + case "Instance.name": + if e.complexity.Instance.Name == nil { + break + } + + return e.complexity.Instance.Name(childComplexity), true + + case "Instance.restarts": + if e.complexity.Instance.Restarts == nil { + break + } + + return e.complexity.Instance.Restarts(childComplexity), true + + case "Instance.status": + if e.complexity.Instance.Status == nil { + break + } + + return e.complexity.Instance.Status(childComplexity), true + + case "InstanceConnection.edges": + if e.complexity.InstanceConnection.Edges == nil { + break + } + + return e.complexity.InstanceConnection.Edges(childComplexity), true + + case "InstanceConnection.nodes": + if e.complexity.InstanceConnection.Nodes == nil { + break + } + + return e.complexity.InstanceConnection.Nodes(childComplexity), true + + case "InstanceConnection.pageInfo": + if e.complexity.InstanceConnection.PageInfo == nil { + break + } + + return e.complexity.InstanceConnection.PageInfo(childComplexity), true + + case "InstanceEdge.cursor": + if e.complexity.InstanceEdge.Cursor == nil { + break + } + + return e.complexity.InstanceEdge.Cursor(childComplexity), true + + case "InstanceEdge.node": + if e.complexity.InstanceEdge.Node == nil { + break + } + + return e.complexity.InstanceEdge.Node(childComplexity), true + + case "InstanceStatus.message": + if e.complexity.InstanceStatus.Message == nil { + break + } + + return e.complexity.InstanceStatus.Message(childComplexity), true + + case "InstanceStatus.state": + if e.complexity.InstanceStatus.State == nil { + break + } + + return e.complexity.InstanceStatus.State(childComplexity), true + case "Job.authIntegrations": if e.complexity.Job.AuthIntegrations == nil { break @@ -7049,7 +7179,19 @@ type Application implements Node & Workload { "The application manifest." manifest: ApplicationManifest! - # instances: [Instance!]! + instances( + "Get the first n items in the connection. This can be used in combination with the after parameter." + first: Int + + "Get items after this cursor." + after: Cursor + + "Get the last n items in the connection. This can be used in combination with the before parameter." + last: Int + + "Get items before this cursor." + before: Cursor + ): InstanceConnection! # autoScaling: AutoScaling! } @@ -7200,6 +7342,45 @@ enum IngressType { INTERNAL AUTHENTICATED } + +type Instance implements Node { + id: ID! + name: String! + image: ContainerImage! + restarts: Int! + created: Time! + status: InstanceStatus! +} + +type InstanceStatus { + state: InstanceState! + message: String! +} + +enum InstanceState { + RUNNING + FAILING + UNKNOWN +} + +type InstanceConnection { + "Pagination information." + pageInfo: PageInfo! + + "List of nodes." + nodes: [Instance!]! + + "List of edges." + edges: [InstanceEdge!]! +} + +type InstanceEdge { + "Cursor for this edge that can be used for pagination." + cursor: Cursor! + + "The instance." + node: Instance! +} `, BuiltIn: false}, {Name: "../schema/auditlog.graphqls", Input: `extend type Team { "Audit entries associated with the team." @@ -10645,6 +10826,119 @@ func (ec *executionContext) field_Application_buckets_argsOrderBy( return zeroVal, nil } +func (ec *executionContext) field_Application_instances_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + arg0, err := ec.field_Application_instances_argsFirst(ctx, rawArgs) + if err != nil { + return nil, err + } + args["first"] = arg0 + arg1, err := ec.field_Application_instances_argsAfter(ctx, rawArgs) + if err != nil { + return nil, err + } + args["after"] = arg1 + arg2, err := ec.field_Application_instances_argsLast(ctx, rawArgs) + if err != nil { + return nil, err + } + args["last"] = arg2 + arg3, err := ec.field_Application_instances_argsBefore(ctx, rawArgs) + if err != nil { + return nil, err + } + args["before"] = arg3 + return args, nil +} +func (ec *executionContext) field_Application_instances_argsFirst( + ctx context.Context, + rawArgs map[string]interface{}, +) (*int, error) { + // We won't call the directive if the argument is null. + // Set call_argument_directives_with_null to true to call directives + // even if the argument is null. + _, ok := rawArgs["first"] + if !ok { + var zeroVal *int + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("first")) + if tmp, ok := rawArgs["first"]; ok { + return ec.unmarshalOInt2ᚖint(ctx, tmp) + } + + var zeroVal *int + return zeroVal, nil +} + +func (ec *executionContext) field_Application_instances_argsAfter( + ctx context.Context, + rawArgs map[string]interface{}, +) (*pagination.Cursor, error) { + // We won't call the directive if the argument is null. + // Set call_argument_directives_with_null to true to call directives + // even if the argument is null. + _, ok := rawArgs["after"] + if !ok { + var zeroVal *pagination.Cursor + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("after")) + if tmp, ok := rawArgs["after"]; ok { + return ec.unmarshalOCursor2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐCursor(ctx, tmp) + } + + var zeroVal *pagination.Cursor + return zeroVal, nil +} + +func (ec *executionContext) field_Application_instances_argsLast( + ctx context.Context, + rawArgs map[string]interface{}, +) (*int, error) { + // We won't call the directive if the argument is null. + // Set call_argument_directives_with_null to true to call directives + // even if the argument is null. + _, ok := rawArgs["last"] + if !ok { + var zeroVal *int + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("last")) + if tmp, ok := rawArgs["last"]; ok { + return ec.unmarshalOInt2ᚖint(ctx, tmp) + } + + var zeroVal *int + return zeroVal, nil +} + +func (ec *executionContext) field_Application_instances_argsBefore( + ctx context.Context, + rawArgs map[string]interface{}, +) (*pagination.Cursor, error) { + // We won't call the directive if the argument is null. + // Set call_argument_directives_with_null to true to call directives + // even if the argument is null. + _, ok := rawArgs["before"] + if !ok { + var zeroVal *pagination.Cursor + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("before")) + if tmp, ok := rawArgs["before"]; ok { + return ec.unmarshalOCursor2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐCursor(ctx, tmp) + } + + var zeroVal *pagination.Cursor + return zeroVal, nil +} + func (ec *executionContext) field_Application_kafkaTopicAcls_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -17138,6 +17432,69 @@ func (ec *executionContext) fieldContext_Application_manifest(_ context.Context, return fc, nil } +func (ec *executionContext) _Application_instances(ctx context.Context, field graphql.CollectedField, obj *application.Application) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Application_instances(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.Application().Instances(rctx, obj, fc.Args["first"].(*int), fc.Args["after"].(*pagination.Cursor), fc.Args["last"].(*int), fc.Args["before"].(*pagination.Cursor)) + }) + 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.(*pagination.Connection[*application.Instance]) + fc.Result = res + return ec.marshalNInstanceConnection2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐConnection(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Application_instances(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Application", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "pageInfo": + return ec.fieldContext_InstanceConnection_pageInfo(ctx, field) + case "nodes": + return ec.fieldContext_InstanceConnection_nodes(ctx, field) + case "edges": + return ec.fieldContext_InstanceConnection_edges(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InstanceConnection", field.Name) + }, + } + 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_Application_instances_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Application_bigQueryDatasets(ctx context.Context, field graphql.CollectedField, obj *application.Application) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Application_bigQueryDatasets(ctx, field) if err != nil { @@ -17831,6 +18188,8 @@ func (ec *executionContext) fieldContext_ApplicationConnection_nodes(_ context.C return ec.fieldContext_Application_authIntegrations(ctx, field) case "manifest": return ec.fieldContext_Application_manifest(ctx, field) + case "instances": + return ec.fieldContext_Application_instances(ctx, field) case "bigQueryDatasets": return ec.fieldContext_Application_bigQueryDatasets(ctx, field) case "buckets": @@ -18009,6 +18368,8 @@ func (ec *executionContext) fieldContext_ApplicationEdge_node(_ context.Context, return ec.fieldContext_Application_authIntegrations(ctx, field) case "manifest": return ec.fieldContext_Application_manifest(ctx, field) + case "instances": + return ec.fieldContext_Application_instances(ctx, field) case "bigQueryDatasets": return ec.fieldContext_Application_bigQueryDatasets(ctx, field) case "buckets": @@ -23222,6 +23583,650 @@ func (ec *executionContext) fieldContext_Ingress_type(_ context.Context, field g return fc, nil } +func (ec *executionContext) _Instance_id(ctx context.Context, field graphql.CollectedField, obj *application.Instance) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Instance_id(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.ID(), 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.(ident.Ident) + fc.Result = res + return ec.marshalNID2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋidentᚐIdent(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Instance_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Instance", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Instance_name(ctx context.Context, field graphql.CollectedField, obj *application.Instance) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Instance_name(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.Name, 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.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Instance_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Instance", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Instance_image(ctx context.Context, field graphql.CollectedField, obj *application.Instance) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Instance_image(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.Image(), 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.(*workload.ContainerImage) + fc.Result = res + return ec.marshalNContainerImage2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚐContainerImage(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Instance_image(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Instance", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_ContainerImage_id(ctx, field) + case "name": + return ec.fieldContext_ContainerImage_name(ctx, field) + case "tag": + return ec.fieldContext_ContainerImage_tag(ctx, field) + case "hasSBOM": + return ec.fieldContext_ContainerImage_hasSBOM(ctx, field) + case "vulnerabilities": + return ec.fieldContext_ContainerImage_vulnerabilities(ctx, field) + case "vulnerabilitySummary": + return ec.fieldContext_ContainerImage_vulnerabilitySummary(ctx, field) + case "workloadReferences": + return ec.fieldContext_ContainerImage_workloadReferences(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ContainerImage", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Instance_restarts(ctx context.Context, field graphql.CollectedField, obj *application.Instance) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Instance_restarts(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.Restarts, 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.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Instance_restarts(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Instance", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Int does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Instance_created(ctx context.Context, field graphql.CollectedField, obj *application.Instance) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Instance_created(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.Created, 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.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Instance_created(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Instance", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Time does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Instance_status(ctx context.Context, field graphql.CollectedField, obj *application.Instance) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Instance_status(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.Status(), 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.(*application.InstanceStatus) + fc.Result = res + return ec.marshalNInstanceStatus2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Instance_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Instance", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "state": + return ec.fieldContext_InstanceStatus_state(ctx, field) + case "message": + return ec.fieldContext_InstanceStatus_message(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InstanceStatus", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *pagination.Connection[*application.Instance]) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceConnection_pageInfo(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.PageInfo, 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.(pagination.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "hasNextPage": + return ec.fieldContext_PageInfo_hasNextPage(ctx, field) + case "endCursor": + return ec.fieldContext_PageInfo_endCursor(ctx, field) + case "hasPreviousPage": + return ec.fieldContext_PageInfo_hasPreviousPage(ctx, field) + case "startCursor": + return ec.fieldContext_PageInfo_startCursor(ctx, field) + case "totalCount": + return ec.fieldContext_PageInfo_totalCount(ctx, field) + case "pageStart": + return ec.fieldContext_PageInfo_pageStart(ctx, field) + case "pageEnd": + return ec.fieldContext_PageInfo_pageEnd(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *pagination.Connection[*application.Instance]) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceConnection_nodes(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.Nodes(), 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.([]*application.Instance) + fc.Result = res + return ec.marshalNInstance2ᚕᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceConnection", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Instance_id(ctx, field) + case "name": + return ec.fieldContext_Instance_name(ctx, field) + case "image": + return ec.fieldContext_Instance_image(ctx, field) + case "restarts": + return ec.fieldContext_Instance_restarts(ctx, field) + case "created": + return ec.fieldContext_Instance_created(ctx, field) + case "status": + return ec.fieldContext_Instance_status(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Instance", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceConnection_edges(ctx context.Context, field graphql.CollectedField, obj *pagination.Connection[*application.Instance]) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceConnection_edges(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.Edges, 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.([]pagination.Edge[*application.Instance]) + fc.Result = res + return ec.marshalNInstanceEdge2ᚕgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐEdgeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceConnection_edges(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "cursor": + return ec.fieldContext_InstanceEdge_cursor(ctx, field) + case "node": + return ec.fieldContext_InstanceEdge_node(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type InstanceEdge", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *pagination.Edge[*application.Instance]) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceEdge_cursor(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.Cursor, 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.(pagination.Cursor) + fc.Result = res + return ec.marshalNCursor2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐCursor(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceEdge_cursor(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceEdge", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Cursor does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceEdge_node(ctx context.Context, field graphql.CollectedField, obj *pagination.Edge[*application.Instance]) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceEdge_node(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.Node, 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.(*application.Instance) + fc.Result = res + return ec.marshalNInstance2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstance(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceEdge_node(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceEdge", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Instance_id(ctx, field) + case "name": + return ec.fieldContext_Instance_name(ctx, field) + case "image": + return ec.fieldContext_Instance_image(ctx, field) + case "restarts": + return ec.fieldContext_Instance_restarts(ctx, field) + case "created": + return ec.fieldContext_Instance_created(ctx, field) + case "status": + return ec.fieldContext_Instance_status(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Instance", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceStatus_state(ctx context.Context, field graphql.CollectedField, obj *application.InstanceStatus) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceStatus_state(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.State, 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.(application.InstanceState) + fc.Result = res + return ec.marshalNInstanceState2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceState(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceStatus_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceStatus", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type InstanceState does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _InstanceStatus_message(ctx context.Context, field graphql.CollectedField, obj *application.InstanceStatus) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_InstanceStatus_message(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.Message, 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.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_InstanceStatus_message(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "InstanceStatus", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Job_id(ctx context.Context, field graphql.CollectedField, obj *job.Job) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Job_id(ctx, field) if err != nil { @@ -34226,6 +35231,8 @@ func (ec *executionContext) fieldContext_RestartApplicationPayload_application(_ return ec.fieldContext_Application_authIntegrations(ctx, field) case "manifest": return ec.fieldContext_Application_manifest(ctx, field) + case "instances": + return ec.fieldContext_Application_instances(ctx, field) case "bigQueryDatasets": return ec.fieldContext_Application_bigQueryDatasets(ctx, field) case "buckets": @@ -43625,6 +44632,8 @@ func (ec *executionContext) fieldContext_TeamEnvironment_application(ctx context return ec.fieldContext_Application_authIntegrations(ctx, field) case "manifest": return ec.fieldContext_Application_manifest(ctx, field) + case "instances": + return ec.fieldContext_Application_instances(ctx, field) case "bigQueryDatasets": return ec.fieldContext_Application_bigQueryDatasets(ctx, field) case "buckets": @@ -55861,6 +56870,20 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj switch obj := (obj).(type) { case nil: return graphql.Null + case sqlinstance.SQLDatabase: + return ec._SqlDatabase(ctx, sel, &obj) + case *sqlinstance.SQLDatabase: + if obj == nil { + return graphql.Null + } + return ec._SqlDatabase(ctx, sel, obj) + case team.TeamMemberAddedAuditEntry: + return ec._TeamMemberAddedAuditEntry(ctx, sel, &obj) + case *team.TeamMemberAddedAuditEntry: + if obj == nil { + return graphql.Null + } + return ec._TeamMemberAddedAuditEntry(ctx, sel, obj) case sqlinstance.SQLInstance: return ec._SqlInstance(ctx, sel, &obj) case *sqlinstance.SQLInstance: @@ -55868,20 +56891,13 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._SqlInstance(ctx, sel, obj) - case team.TeamMemberRemovedAuditEntry: - return ec._TeamMemberRemovedAuditEntry(ctx, sel, &obj) - case *team.TeamMemberRemovedAuditEntry: - if obj == nil { - return graphql.Null - } - return ec._TeamMemberRemovedAuditEntry(ctx, sel, obj) - case application.Application: - return ec._Application(ctx, sel, &obj) - case *application.Application: + case bigquery.BigQueryDataset: + return ec._BigQueryDataset(ctx, sel, &obj) + case *bigquery.BigQueryDataset: if obj == nil { return graphql.Null } - return ec._Application(ctx, sel, obj) + return ec._BigQueryDataset(ctx, sel, obj) case bucket.Bucket: return ec._Bucket(ctx, sel, &obj) case *bucket.Bucket: @@ -55889,20 +56905,20 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._Bucket(ctx, sel, obj) - case team.TeamEnvironmentUpdatedAuditEntry: - return ec._TeamEnvironmentUpdatedAuditEntry(ctx, sel, &obj) - case *team.TeamEnvironmentUpdatedAuditEntry: + case job.Job: + return ec._Job(ctx, sel, &obj) + case *job.Job: if obj == nil { return graphql.Null } - return ec._TeamEnvironmentUpdatedAuditEntry(ctx, sel, obj) - case team.TeamMemberSetRoleAuditEntry: - return ec._TeamMemberSetRoleAuditEntry(ctx, sel, &obj) - case *team.TeamMemberSetRoleAuditEntry: + return ec._Job(ctx, sel, obj) + case application.Application: + return ec._Application(ctx, sel, &obj) + case *application.Application: if obj == nil { return graphql.Null } - return ec._TeamMemberSetRoleAuditEntry(ctx, sel, obj) + return ec._Application(ctx, sel, obj) case kafkatopic.KafkaTopic: return ec._KafkaTopic(ctx, sel, &obj) case *kafkatopic.KafkaTopic: @@ -55917,13 +56933,13 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._OpenSearch(ctx, sel, obj) - case team.TeamMemberAddedAuditEntry: - return ec._TeamMemberAddedAuditEntry(ctx, sel, &obj) - case *team.TeamMemberAddedAuditEntry: + case team.TeamEnvironmentUpdatedAuditEntry: + return ec._TeamEnvironmentUpdatedAuditEntry(ctx, sel, &obj) + case *team.TeamEnvironmentUpdatedAuditEntry: if obj == nil { return graphql.Null } - return ec._TeamMemberAddedAuditEntry(ctx, sel, obj) + return ec._TeamEnvironmentUpdatedAuditEntry(ctx, sel, obj) case redis.RedisInstance: return ec._RedisInstance(ctx, sel, &obj) case *redis.RedisInstance: @@ -55931,20 +56947,20 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._RedisInstance(ctx, sel, obj) - case team.TeamConfirmDeleteKeyAuditEntry: - return ec._TeamConfirmDeleteKeyAuditEntry(ctx, sel, &obj) - case *team.TeamConfirmDeleteKeyAuditEntry: + case team.TeamMemberSetRoleAuditEntry: + return ec._TeamMemberSetRoleAuditEntry(ctx, sel, &obj) + case *team.TeamMemberSetRoleAuditEntry: if obj == nil { return graphql.Null } - return ec._TeamConfirmDeleteKeyAuditEntry(ctx, sel, obj) - case team.TeamCreateDeleteKeyAuditEntry: - return ec._TeamCreateDeleteKeyAuditEntry(ctx, sel, &obj) - case *team.TeamCreateDeleteKeyAuditEntry: + return ec._TeamMemberSetRoleAuditEntry(ctx, sel, obj) + case team.TeamMemberRemovedAuditEntry: + return ec._TeamMemberRemovedAuditEntry(ctx, sel, &obj) + case *team.TeamMemberRemovedAuditEntry: if obj == nil { return graphql.Null } - return ec._TeamCreateDeleteKeyAuditEntry(ctx, sel, obj) + return ec._TeamMemberRemovedAuditEntry(ctx, sel, obj) case secret.SecretCreatedAuditEntry: return ec._SecretCreatedAuditEntry(ctx, sel, &obj) case *secret.SecretCreatedAuditEntry: @@ -55952,27 +56968,20 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._SecretCreatedAuditEntry(ctx, sel, obj) - case sqlinstance.SQLDatabase: - return ec._SqlDatabase(ctx, sel, &obj) - case *sqlinstance.SQLDatabase: - if obj == nil { - return graphql.Null - } - return ec._SqlDatabase(ctx, sel, obj) - case bigquery.BigQueryDataset: - return ec._BigQueryDataset(ctx, sel, &obj) - case *bigquery.BigQueryDataset: + case team.TeamConfirmDeleteKeyAuditEntry: + return ec._TeamConfirmDeleteKeyAuditEntry(ctx, sel, &obj) + case *team.TeamConfirmDeleteKeyAuditEntry: if obj == nil { return graphql.Null } - return ec._BigQueryDataset(ctx, sel, obj) - case job.Job: - return ec._Job(ctx, sel, &obj) - case *job.Job: + return ec._TeamConfirmDeleteKeyAuditEntry(ctx, sel, obj) + case team.TeamCreateDeleteKeyAuditEntry: + return ec._TeamCreateDeleteKeyAuditEntry(ctx, sel, &obj) + case *team.TeamCreateDeleteKeyAuditEntry: if obj == nil { return graphql.Null } - return ec._Job(ctx, sel, obj) + return ec._TeamCreateDeleteKeyAuditEntry(ctx, sel, obj) case team.TeamUpdatedAuditEntry: return ec._TeamUpdatedAuditEntry(ctx, sel, &obj) case *team.TeamUpdatedAuditEntry: @@ -55987,13 +56996,6 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._TeamCreatedAuditEntry(ctx, sel, obj) - case secret.Secret: - return ec._Secret(ctx, sel, &obj) - case *secret.Secret: - if obj == nil { - return graphql.Null - } - return ec._Secret(ctx, sel, obj) case team.TeamEnvironment: return ec._TeamEnvironment(ctx, sel, &obj) case *team.TeamEnvironment: @@ -56001,37 +57003,51 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._TeamEnvironment(ctx, sel, obj) - case repository.Repository: - return ec._Repository(ctx, sel, &obj) - case *repository.Repository: + case team.Team: + return ec._Team(ctx, sel, &obj) + case *team.Team: if obj == nil { return graphql.Null } - return ec._Repository(ctx, sel, obj) - case persistence.Persistence: + return ec._Team(ctx, sel, obj) + case auditv1.AuditEntry: if obj == nil { return graphql.Null } - return ec._Persistence(ctx, sel, obj) - case auditv1.AuditEntry: + return ec._AuditEntry(ctx, sel, obj) + case workload.ContainerImage: + return ec._ContainerImage(ctx, sel, &obj) + case *workload.ContainerImage: if obj == nil { return graphql.Null } - return ec._AuditEntry(ctx, sel, obj) - case job.JobRun: - return ec._JobRun(ctx, sel, &obj) - case *job.JobRun: + return ec._ContainerImage(ctx, sel, obj) + case application.Instance: + return ec._Instance(ctx, sel, &obj) + case *application.Instance: if obj == nil { return graphql.Null } - return ec._JobRun(ctx, sel, obj) - case team.Team: - return ec._Team(ctx, sel, &obj) - case *team.Team: + return ec._Instance(ctx, sel, obj) + case secret.Secret: + return ec._Secret(ctx, sel, &obj) + case *secret.Secret: if obj == nil { return graphql.Null } - return ec._Team(ctx, sel, obj) + return ec._Secret(ctx, sel, obj) + case repository.Repository: + return ec._Repository(ctx, sel, &obj) + case *repository.Repository: + if obj == nil { + return graphql.Null + } + return ec._Repository(ctx, sel, obj) + case persistence.Persistence: + if obj == nil { + return graphql.Null + } + return ec._Persistence(ctx, sel, obj) case user.User: return ec._User(ctx, sel, &obj) case *user.User: @@ -56051,13 +57067,13 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._Workload(ctx, sel, obj) - case workload.ContainerImage: - return ec._ContainerImage(ctx, sel, &obj) - case *workload.ContainerImage: + case job.JobRun: + return ec._JobRun(ctx, sel, &obj) + case *job.JobRun: if obj == nil { return graphql.Null } - return ec._ContainerImage(ctx, sel, obj) + return ec._JobRun(ctx, sel, obj) default: panic(fmt.Errorf("unexpected type %T", obj)) } @@ -56612,6 +57628,42 @@ func (ec *executionContext) _Application(ctx context.Context, sel ast.SelectionS continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "instances": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Application_instances(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + 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) }) case "bigQueryDatasets": field := field @@ -59227,19 +60279,158 @@ func (ec *executionContext) _ImageVulnerabilitySummary(ctx context.Context, sel return out } -var inboundNetworkPolicyImplementors = []string{"InboundNetworkPolicy"} +var inboundNetworkPolicyImplementors = []string{"InboundNetworkPolicy"} + +func (ec *executionContext) _InboundNetworkPolicy(ctx context.Context, sel ast.SelectionSet, obj *netpol.InboundNetworkPolicy) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, inboundNetworkPolicyImplementors) + + 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("InboundNetworkPolicy") + case "rules": + out.Values[i] = ec._InboundNetworkPolicy_rules(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 ingressImplementors = []string{"Ingress"} + +func (ec *executionContext) _Ingress(ctx context.Context, sel ast.SelectionSet, obj *application.Ingress) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, ingressImplementors) + + 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("Ingress") + case "url": + out.Values[i] = ec._Ingress_url(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "type": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Ingress_type(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + 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)) + } + } + 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 instanceImplementors = []string{"Instance", "Node"} -func (ec *executionContext) _InboundNetworkPolicy(ctx context.Context, sel ast.SelectionSet, obj *netpol.InboundNetworkPolicy) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, inboundNetworkPolicyImplementors) +func (ec *executionContext) _Instance(ctx context.Context, sel ast.SelectionSet, obj *application.Instance) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, instanceImplementors) 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("InboundNetworkPolicy") - case "rules": - out.Values[i] = ec._InboundNetworkPolicy_rules(ctx, field, obj) + out.Values[i] = graphql.MarshalString("Instance") + case "id": + out.Values[i] = ec._Instance_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec._Instance_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "image": + out.Values[i] = ec._Instance_image(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "restarts": + out.Values[i] = ec._Instance_restarts(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "created": + out.Values[i] = ec._Instance_created(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "status": + out.Values[i] = ec._Instance_status(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -59266,58 +60457,120 @@ func (ec *executionContext) _InboundNetworkPolicy(ctx context.Context, sel ast.S return out } -var ingressImplementors = []string{"Ingress"} +var instanceConnectionImplementors = []string{"InstanceConnection"} -func (ec *executionContext) _Ingress(ctx context.Context, sel ast.SelectionSet, obj *application.Ingress) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, ingressImplementors) +func (ec *executionContext) _InstanceConnection(ctx context.Context, sel ast.SelectionSet, obj *pagination.Connection[*application.Instance]) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, instanceConnectionImplementors) 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("Ingress") - case "url": - out.Values[i] = ec._Ingress_url(ctx, field, obj) + out.Values[i] = graphql.MarshalString("InstanceConnection") + case "pageInfo": + out.Values[i] = ec._InstanceConnection_pageInfo(ctx, field, obj) if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) + out.Invalids++ } - case "type": - field := field - - innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Ingress_type(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res + case "nodes": + out.Values[i] = ec._InstanceConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "edges": + out.Values[i] = ec._InstanceConnection_edges(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 + } - 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) - }) + atomic.AddInt32(&ec.deferred, int32(len(deferred))) - // don't run the out.Concurrently() call below - out.Values[i] = graphql.Null - continue + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var instanceEdgeImplementors = []string{"InstanceEdge"} + +func (ec *executionContext) _InstanceEdge(ctx context.Context, sel ast.SelectionSet, obj *pagination.Edge[*application.Instance]) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, instanceEdgeImplementors) + + 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("InstanceEdge") + case "cursor": + out.Values[i] = ec._InstanceEdge_cursor(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ } + case "node": + out.Values[i] = ec._InstanceEdge_node(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 + } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + 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 instanceStatusImplementors = []string{"InstanceStatus"} + +func (ec *executionContext) _InstanceStatus(ctx context.Context, sel ast.SelectionSet, obj *application.InstanceStatus) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, instanceStatusImplementors) + + 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("InstanceStatus") + case "state": + out.Values[i] = ec._InstanceStatus_state(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "message": + out.Values[i] = ec._InstanceStatus_message(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -72291,6 +73544,142 @@ func (ec *executionContext) marshalNIngressType2githubᚗcomᚋnaisᚋapiᚋinte return v } +func (ec *executionContext) marshalNInstance2ᚕᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceᚄ(ctx context.Context, sel ast.SelectionSet, v []*application.Instance) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNInstance2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstance(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNInstance2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstance(ctx context.Context, sel ast.SelectionSet, v *application.Instance) 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") + } + return graphql.Null + } + return ec._Instance(ctx, sel, v) +} + +func (ec *executionContext) marshalNInstanceConnection2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐConnection(ctx context.Context, sel ast.SelectionSet, v pagination.Connection[*application.Instance]) graphql.Marshaler { + return ec._InstanceConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNInstanceConnection2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐConnection(ctx context.Context, sel ast.SelectionSet, v *pagination.Connection[*application.Instance]) 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") + } + return graphql.Null + } + return ec._InstanceConnection(ctx, sel, v) +} + +func (ec *executionContext) marshalNInstanceEdge2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐEdge(ctx context.Context, sel ast.SelectionSet, v pagination.Edge[*application.Instance]) graphql.Marshaler { + return ec._InstanceEdge(ctx, sel, &v) +} + +func (ec *executionContext) marshalNInstanceEdge2ᚕgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐEdgeᚄ(ctx context.Context, sel ast.SelectionSet, v []pagination.Edge[*application.Instance]) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNInstanceEdge2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋgraphv1ᚋpaginationᚐEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNInstanceState2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceState(ctx context.Context, v interface{}) (application.InstanceState, error) { + var res application.InstanceState + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInstanceState2githubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceState(ctx context.Context, sel ast.SelectionSet, v application.InstanceState) graphql.Marshaler { + return v +} + +func (ec *executionContext) marshalNInstanceStatus2ᚖgithubᚗcomᚋnaisᚋapiᚋinternalᚋv1ᚋworkloadᚋapplicationᚐInstanceStatus(ctx context.Context, sel ast.SelectionSet, v *application.InstanceStatus) 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") + } + return graphql.Null + } + return ec._InstanceStatus(ctx, sel, v) +} + func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { res, err := graphql.UnmarshalInt(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/internal/v1/graphv1/schema/applications.graphqls b/internal/v1/graphv1/schema/applications.graphqls index 6ca03dad2..f93a4ea15 100644 --- a/internal/v1/graphv1/schema/applications.graphqls +++ b/internal/v1/graphv1/schema/applications.graphqls @@ -74,7 +74,19 @@ type Application implements Node & Workload { "The application manifest." manifest: ApplicationManifest! - # instances: [Instance!]! + instances( + "Get the first n items in the connection. This can be used in combination with the after parameter." + first: Int + + "Get items after this cursor." + after: Cursor + + "Get the last n items in the connection. This can be used in combination with the before parameter." + last: Int + + "Get items before this cursor." + before: Cursor + ): InstanceConnection! # autoScaling: AutoScaling! } @@ -225,3 +237,42 @@ enum IngressType { INTERNAL AUTHENTICATED } + +type Instance implements Node { + id: ID! + name: String! + image: ContainerImage! + restarts: Int! + created: Time! + status: InstanceStatus! +} + +type InstanceStatus { + state: InstanceState! + message: String! +} + +enum InstanceState { + RUNNING + FAILING + UNKNOWN +} + +type InstanceConnection { + "Pagination information." + pageInfo: PageInfo! + + "List of nodes." + nodes: [Instance!]! + + "List of edges." + edges: [InstanceEdge!]! +} + +type InstanceEdge { + "Cursor for this edge that can be used for pagination." + cursor: Cursor! + + "The instance." + node: Instance! +} diff --git a/internal/v1/status/check_no_running_instances.go b/internal/v1/status/check_no_running_instances.go index 443f8f6ea..3ec0b9187 100644 --- a/internal/v1/status/check_no_running_instances.go +++ b/internal/v1/status/check_no_running_instances.go @@ -20,7 +20,7 @@ func (c checkAppNoRunningInstances) Run(ctx context.Context, w workload.Workload func (checkAppNoRunningInstances) run(ctx context.Context, w workload.Workload) WorkloadStatusError { app := w.(*application.Application) - instances, err := application.ListAllInstances(ctx, app.EnvironmentName, app.TeamSlug, app.Name) + instances, err := application.ListAllInstances(ctx, app.TeamSlug, app.EnvironmentName, app.Name) if err != nil { return nil } diff --git a/internal/v1/workload/application/models.go b/internal/v1/workload/application/models.go index e9e6b8669..4d9650e53 100644 --- a/internal/v1/workload/application/models.go +++ b/internal/v1/workload/application/models.go @@ -22,6 +22,8 @@ import ( type ( ApplicationConnection = pagination.Connection[*Application] ApplicationEdge = pagination.Edge[*Application] + InstanceConnection = pagination.Connection[*Instance] + InstanceEdge = pagination.Edge[*Instance] ) type Application struct { @@ -42,25 +44,63 @@ type Instance struct { Restarts int `json:"restarts"` Created time.Time `json:"created"` - ImageString string `json:"-"` - EnvironmentName string `json:"-"` - Spec *corev1.Pod - WorkloadContainerStatus corev1.ContainerStatus + ImageString string `json:"-"` + EnvironmentName string `json:"-"` + TeamSlug slug.Slug `json:"-"` + ApplicationName string `json:"-"` + Spec *corev1.Pod `json:"-"` + ApplicationContainerStatus corev1.ContainerStatus `json:"-"` } -func toGraphInstance(pod *corev1.Pod, environmentName string, workloadName string) *Instance { +func (Instance) IsNode() {} + +func (i Instance) ID() ident.Ident { + return newInstanceIdent(i.TeamSlug, i.EnvironmentName, i.ApplicationName, i.Name) +} + +func (i *Instance) Status() *InstanceStatus { + switch { + case i.ApplicationContainerStatus.State.Running != nil: + return &InstanceStatus{ + State: InstanceStateRunning, + Message: "Running", + } + case i.ApplicationContainerStatus.State.Terminated != nil: + return &InstanceStatus{ + State: InstanceStateFailing, + Message: i.ApplicationContainerStatus.State.Waiting.Reason, + } + default: + return &InstanceStatus{ + State: InstanceStateUnknown, + Message: "Unknown", + } + } +} + +func toGraphInstance(pod *corev1.Pod, teamSlug slug.Slug, environmentName string, applicationName string) *Instance { + var containerStatus corev1.ContainerStatus + for _, c := range pod.Status.ContainerStatuses { + if c.Name == applicationName { + containerStatus = c + break + } + } + ret := &Instance{ Name: pod.Name, - Restarts: int(pod.Status.ContainerStatuses[0].RestartCount), + Restarts: int(containerStatus.RestartCount), Created: pod.CreationTimestamp.Time, Spec: pod, EnvironmentName: environmentName, ImageString: pod.Spec.Containers[0].Image, + TeamSlug: teamSlug, + ApplicationName: applicationName, } for _, c := range pod.Status.ContainerStatuses { - if c.Name == workloadName { - ret.WorkloadContainerStatus = c + if c.Name == applicationName { + ret.ApplicationContainerStatus = c break } } @@ -78,9 +118,9 @@ func (i Instance) Image() *workload.ContainerImage { func (i *Instance) State() InstanceState { switch { - case i.WorkloadContainerStatus.State.Running != nil: + case i.ApplicationContainerStatus.State.Running != nil: return InstanceStateRunning - case i.WorkloadContainerStatus.State.Waiting != nil: + case i.ApplicationContainerStatus.State.Waiting != nil: return InstanceStateFailing default: return InstanceStateUnknown @@ -384,3 +424,8 @@ func (e *IngressType) UnmarshalGQL(v interface{}) error { func (e IngressType) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } + +type InstanceStatus struct { + State InstanceState `json:"state"` + Message string `json:"message"` +} diff --git a/internal/v1/workload/application/node.go b/internal/v1/workload/application/node.go index 7ad79dd8d..755bbd8bd 100644 --- a/internal/v1/workload/application/node.go +++ b/internal/v1/workload/application/node.go @@ -11,16 +11,22 @@ type identType int const ( identKey identType = iota + identInstanceKey ) func init() { ident.RegisterIdentType(identKey, "A", GetByIdent) + ident.RegisterIdentType(identInstanceKey, "INS", getInstanceByIdent) } func newIdent(teamSlug slug.Slug, environment, name string) ident.Ident { return ident.NewIdent(identKey, teamSlug.String(), environment, name) } +func newInstanceIdent(teamSlug slug.Slug, environment, applicationName, instanceName string) ident.Ident { + return ident.NewIdent(identInstanceKey, teamSlug.String(), environment, applicationName, instanceName) +} + func parseIdent(id ident.Ident) (teamSlug slug.Slug, environment, name string, err error) { parts := id.Parts() if len(parts) != 3 { @@ -29,3 +35,12 @@ func parseIdent(id ident.Ident) (teamSlug slug.Slug, environment, name string, e return slug.Slug(parts[0]), parts[1], parts[2], nil } + +func parseInstanceIdent(id ident.Ident) (teamSlug slug.Slug, environment, applicationName, instanceName string, err error) { + parts := id.Parts() + if len(parts) != 3 { + return "", "", "", "", fmt.Errorf("invalid application ident") + } + + return slug.Slug(parts[0]), parts[1], parts[2], parts[3], nil +} diff --git a/internal/v1/workload/application/queries.go b/internal/v1/workload/application/queries.go index 173fcdbc9..eb1ba3d6a 100644 --- a/internal/v1/workload/application/queries.go +++ b/internal/v1/workload/application/queries.go @@ -162,7 +162,17 @@ func Restart(ctx context.Context, teamSlug slug.Slug, environmentName, name stri return nil } -func ListAllInstances(ctx context.Context, environmentName string, teamSlug slug.Slug, appName string) ([]*Instance, error) { +func ListInstances(ctx context.Context, teamSlug slug.Slug, environmentName, appName string, page *pagination.Pagination) (*InstanceConnection, error) { + ret, err := ListAllInstances(ctx, teamSlug, environmentName, appName) + if err != nil { + return nil, err + } + + apps := pagination.Slice(ret, page) + return pagination.NewConnection(apps, page, int32(len(ret))), nil +} + +func ListAllInstances(ctx context.Context, teamSlug slug.Slug, environmentName, appName string) ([]*Instance, error) { pods, err := workload.ListAllPods(ctx, environmentName, teamSlug, appName) if err != nil { return nil, err @@ -170,11 +180,25 @@ func ListAllInstances(ctx context.Context, environmentName string, teamSlug slug ret := make([]*Instance, len(pods)) for i, pod := range pods { - ret[i] = toGraphInstance(pod, environmentName, appName) + ret[i] = toGraphInstance(pod, teamSlug, environmentName, appName) } return ret, nil } +func getInstanceByIdent(ctx context.Context, ident ident.Ident) (*Instance, error) { + teamSlug, env, appName, instanceName, err := parseInstanceIdent(ident) + if err != nil { + return nil, err + } + + pod, err := workload.GetPod(ctx, env, teamSlug, instanceName) + if err != nil { + return nil, err + } + + return toGraphInstance(pod, teamSlug, env, appName), nil +} + func GetIngressType(ctx context.Context, ingress *Ingress) IngressType { uri, err := url.Parse(ingress.URL) if err != nil { diff --git a/internal/v1/workload/queries.go b/internal/v1/workload/queries.go index a6da3981e..54cc88604 100644 --- a/internal/v1/workload/queries.go +++ b/internal/v1/workload/queries.go @@ -71,8 +71,8 @@ func ListAllPods(ctx context.Context, environmentName string, teamSlug slug.Slug if err != nil { return nil, err } - selector := labels.NewSelector().Add(*nameReq) + pods := fromContext(ctx).podWatcher.GetByNamespace(teamSlug.String(), watcher.WithLabels(selector)) ret := []*v1.Pod{} for _, pod := range pods { @@ -85,3 +85,7 @@ func ListAllPods(ctx context.Context, environmentName string, teamSlug slug.Slug return ret, nil } + +func GetPod(ctx context.Context, environmentName string, teamSlug slug.Slug, instanceName string) (*v1.Pod, error) { + return fromContext(ctx).podWatcher.Get(environmentName, teamSlug.String(), instanceName) +}