From f35b67e3721e5cc689e536ca706179fbb32684dc Mon Sep 17 00:00:00 2001 From: KCarretto Date: Mon, 22 Jan 2024 23:08:34 +0000 Subject: [PATCH 1/3] generated entgo --- tavern/internal/c2/c2.proto | 20 + tavern/internal/c2/c2pb/c2.pb.go | 398 +++++-- tavern/internal/c2/c2pb/c2_grpc.pb.go | 40 + tavern/internal/ent/client.go | 205 +++- tavern/internal/ent/ent.go | 18 +- tavern/internal/ent/gql_collection.go | 90 ++ tavern/internal/ent/gql_edge.go | 12 + tavern/internal/ent/gql_node.go | 32 + tavern/internal/ent/gql_pagination.go | 247 ++++ tavern/internal/ent/gql_where_input.go | 289 +++++ tavern/internal/ent/hook/hook.go | 12 + tavern/internal/ent/migrate/schema.go | 24 + tavern/internal/ent/mutation.go | 619 +++++++++- tavern/internal/ent/predicate/predicate.go | 3 + tavern/internal/ent/privacy/privacy.go | 24 + tavern/internal/ent/process.go | 135 +++ tavern/internal/ent/process/process.go | 79 ++ tavern/internal/ent/process/where.go | 253 ++++ tavern/internal/ent/process_create.go | 585 ++++++++++ tavern/internal/ent/process_delete.go | 88 ++ tavern/internal/ent/process_query.go | 544 +++++++++ tavern/internal/ent/process_update.go | 275 +++++ tavern/internal/ent/runtime/runtime.go | 7 + tavern/internal/ent/schema/process.go | 54 + tavern/internal/ent/schema/task.go | 2 + tavern/internal/ent/task.go | 46 +- tavern/internal/ent/task/task.go | 30 + tavern/internal/ent/task/where.go | 23 + tavern/internal/ent/task_create.go | 32 + tavern/internal/ent/task_query.go | 132 ++- tavern/internal/ent/task_update.go | 163 +++ tavern/internal/ent/tx.go | 3 + tavern/internal/graphql/ent.resolvers.go | 56 + .../graphql/generated/ent.generated.go | 1029 ++++++++++++++++- .../graphql/generated/mutation.generated.go | 4 + .../graphql/generated/root_.generated.go | 137 ++- tavern/internal/graphql/gqlgen.yml | 1 + tavern/internal/graphql/schema.graphql | 69 ++ tavern/internal/graphql/schema/ent.graphql | 69 ++ tavern/internal/www/schema.graphql | 69 ++ 40 files changed, 5679 insertions(+), 239 deletions(-) create mode 100644 tavern/internal/ent/process.go create mode 100644 tavern/internal/ent/process/process.go create mode 100644 tavern/internal/ent/process/where.go create mode 100644 tavern/internal/ent/process_create.go create mode 100644 tavern/internal/ent/process_delete.go create mode 100644 tavern/internal/ent/process_query.go create mode 100644 tavern/internal/ent/process_update.go create mode 100644 tavern/internal/ent/schema/process.go diff --git a/tavern/internal/c2/c2.proto b/tavern/internal/c2/c2.proto index 1e0b1a522..2306a49c9 100644 --- a/tavern/internal/c2/c2.proto +++ b/tavern/internal/c2/c2.proto @@ -69,6 +69,13 @@ message TaskOutput { google.protobuf.Timestamp exec_finished_at = 5; } +// Process running on the system. +message Process { + uint64 pid = 1; + string name = 2; + string principal = 3; +} + /* * RPC Messages */ @@ -94,6 +101,13 @@ message DownloadFileResponse { bytes chunk = 1; } +message ReportProcessListRequest { + repeated Process list = 1; + int64 task_id = 2; +} + +message ReportProcessListResponse {} + /* * Service */ @@ -102,6 +116,12 @@ service C2 { rpc ClaimTasks(ClaimTasksRequest) returns (ClaimTasksResponse) {} rpc ReportTaskOutput(ReportTaskOutputRequest) returns (ReportTaskOutputResponse) {} + /* + * Report the active list of running processes. This list will replace any previously reported + * lists for the same host. + */ + rpc ReportProcessList(ReportProcessListRequest) returns (ReportProcessListResponse); + /* * Download a file from the server, returning one or more chunks of data. * The maximum size of these chunks is determined by the server. diff --git a/tavern/internal/c2/c2pb/c2.pb.go b/tavern/internal/c2/c2pb/c2.pb.go index e89e4c631..052e99f89 100644 --- a/tavern/internal/c2/c2pb/c2.pb.go +++ b/tavern/internal/c2/c2pb/c2.pb.go @@ -486,6 +486,70 @@ func (x *TaskOutput) GetExecFinishedAt() *timestamp.Timestamp { return nil } +// Process running on the system. +type Process struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pid uint64 `protobuf:"varint,1,opt,name=pid,proto3" json:"pid,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Principal string `protobuf:"bytes,3,opt,name=principal,proto3" json:"principal,omitempty"` +} + +func (x *Process) Reset() { + *x = Process{} + if protoimpl.UnsafeEnabled { + mi := &file_c2_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Process) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Process) ProtoMessage() {} + +func (x *Process) ProtoReflect() protoreflect.Message { + mi := &file_c2_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Process.ProtoReflect.Descriptor instead. +func (*Process) Descriptor() ([]byte, []int) { + return file_c2_proto_rawDescGZIP(), []int{6} +} + +func (x *Process) GetPid() uint64 { + if x != nil { + return x.Pid + } + return 0 +} + +func (x *Process) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Process) GetPrincipal() string { + if x != nil { + return x.Principal + } + return "" +} + // RPC Messages type ClaimTasksRequest struct { state protoimpl.MessageState @@ -498,7 +562,7 @@ type ClaimTasksRequest struct { func (x *ClaimTasksRequest) Reset() { *x = ClaimTasksRequest{} if protoimpl.UnsafeEnabled { - mi := &file_c2_proto_msgTypes[6] + mi := &file_c2_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -511,7 +575,7 @@ func (x *ClaimTasksRequest) String() string { func (*ClaimTasksRequest) ProtoMessage() {} func (x *ClaimTasksRequest) ProtoReflect() protoreflect.Message { - mi := &file_c2_proto_msgTypes[6] + mi := &file_c2_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -524,7 +588,7 @@ func (x *ClaimTasksRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimTasksRequest.ProtoReflect.Descriptor instead. func (*ClaimTasksRequest) Descriptor() ([]byte, []int) { - return file_c2_proto_rawDescGZIP(), []int{6} + return file_c2_proto_rawDescGZIP(), []int{7} } func (x *ClaimTasksRequest) GetBeacon() *Beacon { @@ -545,7 +609,7 @@ type ClaimTasksResponse struct { func (x *ClaimTasksResponse) Reset() { *x = ClaimTasksResponse{} if protoimpl.UnsafeEnabled { - mi := &file_c2_proto_msgTypes[7] + mi := &file_c2_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -558,7 +622,7 @@ func (x *ClaimTasksResponse) String() string { func (*ClaimTasksResponse) ProtoMessage() {} func (x *ClaimTasksResponse) ProtoReflect() protoreflect.Message { - mi := &file_c2_proto_msgTypes[7] + mi := &file_c2_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -571,7 +635,7 @@ func (x *ClaimTasksResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimTasksResponse.ProtoReflect.Descriptor instead. func (*ClaimTasksResponse) Descriptor() ([]byte, []int) { - return file_c2_proto_rawDescGZIP(), []int{7} + return file_c2_proto_rawDescGZIP(), []int{8} } func (x *ClaimTasksResponse) GetTasks() []*Task { @@ -592,7 +656,7 @@ type ReportTaskOutputRequest struct { func (x *ReportTaskOutputRequest) Reset() { *x = ReportTaskOutputRequest{} if protoimpl.UnsafeEnabled { - mi := &file_c2_proto_msgTypes[8] + mi := &file_c2_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -605,7 +669,7 @@ func (x *ReportTaskOutputRequest) String() string { func (*ReportTaskOutputRequest) ProtoMessage() {} func (x *ReportTaskOutputRequest) ProtoReflect() protoreflect.Message { - mi := &file_c2_proto_msgTypes[8] + mi := &file_c2_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -618,7 +682,7 @@ func (x *ReportTaskOutputRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportTaskOutputRequest.ProtoReflect.Descriptor instead. func (*ReportTaskOutputRequest) Descriptor() ([]byte, []int) { - return file_c2_proto_rawDescGZIP(), []int{8} + return file_c2_proto_rawDescGZIP(), []int{9} } func (x *ReportTaskOutputRequest) GetOutput() *TaskOutput { @@ -637,7 +701,7 @@ type ReportTaskOutputResponse struct { func (x *ReportTaskOutputResponse) Reset() { *x = ReportTaskOutputResponse{} if protoimpl.UnsafeEnabled { - mi := &file_c2_proto_msgTypes[9] + mi := &file_c2_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -650,7 +714,7 @@ func (x *ReportTaskOutputResponse) String() string { func (*ReportTaskOutputResponse) ProtoMessage() {} func (x *ReportTaskOutputResponse) ProtoReflect() protoreflect.Message { - mi := &file_c2_proto_msgTypes[9] + mi := &file_c2_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -663,7 +727,7 @@ func (x *ReportTaskOutputResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ReportTaskOutputResponse.ProtoReflect.Descriptor instead. func (*ReportTaskOutputResponse) Descriptor() ([]byte, []int) { - return file_c2_proto_rawDescGZIP(), []int{9} + return file_c2_proto_rawDescGZIP(), []int{10} } type DownloadFileRequest struct { @@ -677,7 +741,7 @@ type DownloadFileRequest struct { func (x *DownloadFileRequest) Reset() { *x = DownloadFileRequest{} if protoimpl.UnsafeEnabled { - mi := &file_c2_proto_msgTypes[10] + mi := &file_c2_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -690,7 +754,7 @@ func (x *DownloadFileRequest) String() string { func (*DownloadFileRequest) ProtoMessage() {} func (x *DownloadFileRequest) ProtoReflect() protoreflect.Message { - mi := &file_c2_proto_msgTypes[10] + mi := &file_c2_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -703,7 +767,7 @@ func (x *DownloadFileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DownloadFileRequest.ProtoReflect.Descriptor instead. func (*DownloadFileRequest) Descriptor() ([]byte, []int) { - return file_c2_proto_rawDescGZIP(), []int{10} + return file_c2_proto_rawDescGZIP(), []int{11} } func (x *DownloadFileRequest) GetName() string { @@ -724,7 +788,7 @@ type DownloadFileResponse struct { func (x *DownloadFileResponse) Reset() { *x = DownloadFileResponse{} if protoimpl.UnsafeEnabled { - mi := &file_c2_proto_msgTypes[11] + mi := &file_c2_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -737,7 +801,7 @@ func (x *DownloadFileResponse) String() string { func (*DownloadFileResponse) ProtoMessage() {} func (x *DownloadFileResponse) ProtoReflect() protoreflect.Message { - mi := &file_c2_proto_msgTypes[11] + mi := &file_c2_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -750,7 +814,7 @@ func (x *DownloadFileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DownloadFileResponse.ProtoReflect.Descriptor instead. func (*DownloadFileResponse) Descriptor() ([]byte, []int) { - return file_c2_proto_rawDescGZIP(), []int{11} + return file_c2_proto_rawDescGZIP(), []int{12} } func (x *DownloadFileResponse) GetChunk() []byte { @@ -760,6 +824,99 @@ func (x *DownloadFileResponse) GetChunk() []byte { return nil } +type ReportProcessListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + List []*Process `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"` + TaskId int64 `protobuf:"varint,2,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` +} + +func (x *ReportProcessListRequest) Reset() { + *x = ReportProcessListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_c2_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportProcessListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportProcessListRequest) ProtoMessage() {} + +func (x *ReportProcessListRequest) ProtoReflect() protoreflect.Message { + mi := &file_c2_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReportProcessListRequest.ProtoReflect.Descriptor instead. +func (*ReportProcessListRequest) Descriptor() ([]byte, []int) { + return file_c2_proto_rawDescGZIP(), []int{13} +} + +func (x *ReportProcessListRequest) GetList() []*Process { + if x != nil { + return x.List + } + return nil +} + +func (x *ReportProcessListRequest) GetTaskId() int64 { + if x != nil { + return x.TaskId + } + return 0 +} + +type ReportProcessListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ReportProcessListResponse) Reset() { + *x = ReportProcessListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_c2_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportProcessListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportProcessListResponse) ProtoMessage() {} + +func (x *ReportProcessListResponse) ProtoReflect() protoreflect.Message { + mi := &file_c2_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReportProcessListResponse.ProtoReflect.Descriptor instead. +func (*ReportProcessListResponse) Descriptor() ([]byte, []int) { + return file_c2_proto_rawDescGZIP(), []int{14} +} + var File_c2_proto protoreflect.FileDescriptor var file_c2_proto_rawDesc = []byte{ @@ -825,43 +982,60 @@ var file_c2_proto_rawDesc = []byte{ 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, - 0x65, 0x78, 0x65, 0x63, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x22, 0x37, - 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x52, - 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x22, 0x34, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, - 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x63, - 0x32, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x22, 0x41, 0x0a, - 0x17, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x32, 0x2e, 0x54, 0x61, - 0x73, 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x22, 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x13, - 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x44, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, - 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x32, 0xd9, 0x01, 0x0a, 0x02, 0x43, 0x32, 0x12, 0x3d, 0x0a, 0x0a, - 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x15, 0x2e, 0x63, 0x32, 0x2e, - 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x32, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x10, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, - 0x1b, 0x2e, 0x63, 0x32, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x32, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0c, - 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x17, 0x2e, 0x63, - 0x32, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x32, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, - 0x01, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6b, 0x63, 0x61, 0x72, 0x72, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x61, 0x76, 0x65, 0x72, 0x6e, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x32, 0x2f, 0x63, 0x32, 0x70, - 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x78, 0x65, 0x63, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x22, 0x4d, + 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x22, 0x37, 0x0a, + 0x11, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x22, 0x0a, 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x52, 0x06, + 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x22, 0x34, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, + 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x05, + 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x63, 0x32, + 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x22, 0x41, 0x0a, 0x17, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x32, 0x2e, 0x54, 0x61, 0x73, + 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, + 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x13, 0x44, + 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, + 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, + 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x54, 0x0a, 0x18, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, + 0x2e, 0x63, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x04, 0x6c, 0x69, 0x73, + 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x22, 0x1b, 0x0a, 0x19, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xab, 0x02, 0x0a, 0x02, 0x43, 0x32, 0x12, 0x3d, + 0x0a, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x15, 0x2e, 0x63, + 0x32, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x32, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x54, 0x61, + 0x73, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, + 0x10, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x12, 0x1b, 0x2e, 0x63, 0x32, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, + 0x6b, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x63, 0x32, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x4f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, + 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x63, 0x32, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x32, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x43, 0x0a, 0x0c, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x17, 0x2e, 0x63, 0x32, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x32, 0x2e, 0x44, + 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x63, 0x61, 0x72, 0x72, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x61, + 0x76, 0x65, 0x72, 0x6e, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x32, + 0x2f, 0x63, 0x32, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -877,46 +1051,52 @@ func file_c2_proto_rawDescGZIP() []byte { } var file_c2_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_c2_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_c2_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_c2_proto_goTypes = []interface{}{ - (Host_Platform)(0), // 0: c2.Host.Platform - (*Host)(nil), // 1: c2.Host - (*Agent)(nil), // 2: c2.Agent - (*Beacon)(nil), // 3: c2.Beacon - (*Task)(nil), // 4: c2.Task - (*TaskError)(nil), // 5: c2.TaskError - (*TaskOutput)(nil), // 6: c2.TaskOutput - (*ClaimTasksRequest)(nil), // 7: c2.ClaimTasksRequest - (*ClaimTasksResponse)(nil), // 8: c2.ClaimTasksResponse - (*ReportTaskOutputRequest)(nil), // 9: c2.ReportTaskOutputRequest - (*ReportTaskOutputResponse)(nil), // 10: c2.ReportTaskOutputResponse - (*DownloadFileRequest)(nil), // 11: c2.DownloadFileRequest - (*DownloadFileResponse)(nil), // 12: c2.DownloadFileResponse - nil, // 13: c2.Task.ParametersEntry - (*timestamp.Timestamp)(nil), // 14: google.protobuf.Timestamp + (Host_Platform)(0), // 0: c2.Host.Platform + (*Host)(nil), // 1: c2.Host + (*Agent)(nil), // 2: c2.Agent + (*Beacon)(nil), // 3: c2.Beacon + (*Task)(nil), // 4: c2.Task + (*TaskError)(nil), // 5: c2.TaskError + (*TaskOutput)(nil), // 6: c2.TaskOutput + (*Process)(nil), // 7: c2.Process + (*ClaimTasksRequest)(nil), // 8: c2.ClaimTasksRequest + (*ClaimTasksResponse)(nil), // 9: c2.ClaimTasksResponse + (*ReportTaskOutputRequest)(nil), // 10: c2.ReportTaskOutputRequest + (*ReportTaskOutputResponse)(nil), // 11: c2.ReportTaskOutputResponse + (*DownloadFileRequest)(nil), // 12: c2.DownloadFileRequest + (*DownloadFileResponse)(nil), // 13: c2.DownloadFileResponse + (*ReportProcessListRequest)(nil), // 14: c2.ReportProcessListRequest + (*ReportProcessListResponse)(nil), // 15: c2.ReportProcessListResponse + nil, // 16: c2.Task.ParametersEntry + (*timestamp.Timestamp)(nil), // 17: google.protobuf.Timestamp } var file_c2_proto_depIdxs = []int32{ 0, // 0: c2.Host.platform:type_name -> c2.Host.Platform 1, // 1: c2.Beacon.host:type_name -> c2.Host 2, // 2: c2.Beacon.agent:type_name -> c2.Agent - 13, // 3: c2.Task.parameters:type_name -> c2.Task.ParametersEntry + 16, // 3: c2.Task.parameters:type_name -> c2.Task.ParametersEntry 5, // 4: c2.TaskOutput.error:type_name -> c2.TaskError - 14, // 5: c2.TaskOutput.exec_started_at:type_name -> google.protobuf.Timestamp - 14, // 6: c2.TaskOutput.exec_finished_at:type_name -> google.protobuf.Timestamp + 17, // 5: c2.TaskOutput.exec_started_at:type_name -> google.protobuf.Timestamp + 17, // 6: c2.TaskOutput.exec_finished_at:type_name -> google.protobuf.Timestamp 3, // 7: c2.ClaimTasksRequest.beacon:type_name -> c2.Beacon 4, // 8: c2.ClaimTasksResponse.tasks:type_name -> c2.Task 6, // 9: c2.ReportTaskOutputRequest.output:type_name -> c2.TaskOutput - 7, // 10: c2.C2.ClaimTasks:input_type -> c2.ClaimTasksRequest - 9, // 11: c2.C2.ReportTaskOutput:input_type -> c2.ReportTaskOutputRequest - 11, // 12: c2.C2.DownloadFile:input_type -> c2.DownloadFileRequest - 8, // 13: c2.C2.ClaimTasks:output_type -> c2.ClaimTasksResponse - 10, // 14: c2.C2.ReportTaskOutput:output_type -> c2.ReportTaskOutputResponse - 12, // 15: c2.C2.DownloadFile:output_type -> c2.DownloadFileResponse - 13, // [13:16] is the sub-list for method output_type - 10, // [10:13] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 7, // 10: c2.ReportProcessListRequest.list:type_name -> c2.Process + 8, // 11: c2.C2.ClaimTasks:input_type -> c2.ClaimTasksRequest + 10, // 12: c2.C2.ReportTaskOutput:input_type -> c2.ReportTaskOutputRequest + 14, // 13: c2.C2.ReportProcessList:input_type -> c2.ReportProcessListRequest + 12, // 14: c2.C2.DownloadFile:input_type -> c2.DownloadFileRequest + 9, // 15: c2.C2.ClaimTasks:output_type -> c2.ClaimTasksResponse + 11, // 16: c2.C2.ReportTaskOutput:output_type -> c2.ReportTaskOutputResponse + 15, // 17: c2.C2.ReportProcessList:output_type -> c2.ReportProcessListResponse + 13, // 18: c2.C2.DownloadFile:output_type -> c2.DownloadFileResponse + 15, // [15:19] is the sub-list for method output_type + 11, // [11:15] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_c2_proto_init() } @@ -998,7 +1178,7 @@ func file_c2_proto_init() { } } file_c2_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClaimTasksRequest); i { + switch v := v.(*Process); i { case 0: return &v.state case 1: @@ -1010,7 +1190,7 @@ func file_c2_proto_init() { } } file_c2_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClaimTasksResponse); i { + switch v := v.(*ClaimTasksRequest); i { case 0: return &v.state case 1: @@ -1022,7 +1202,7 @@ func file_c2_proto_init() { } } file_c2_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReportTaskOutputRequest); i { + switch v := v.(*ClaimTasksResponse); i { case 0: return &v.state case 1: @@ -1034,7 +1214,7 @@ func file_c2_proto_init() { } } file_c2_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReportTaskOutputResponse); i { + switch v := v.(*ReportTaskOutputRequest); i { case 0: return &v.state case 1: @@ -1046,7 +1226,7 @@ func file_c2_proto_init() { } } file_c2_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DownloadFileRequest); i { + switch v := v.(*ReportTaskOutputResponse); i { case 0: return &v.state case 1: @@ -1058,6 +1238,18 @@ func file_c2_proto_init() { } } file_c2_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DownloadFileRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_c2_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DownloadFileResponse); i { case 0: return &v.state @@ -1069,6 +1261,30 @@ func file_c2_proto_init() { return nil } } + file_c2_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportProcessListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_c2_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportProcessListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1076,7 +1292,7 @@ func file_c2_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_c2_proto_rawDesc, NumEnums: 1, - NumMessages: 13, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, diff --git a/tavern/internal/c2/c2pb/c2_grpc.pb.go b/tavern/internal/c2/c2pb/c2_grpc.pb.go index ef5f45110..f7f22d65a 100644 --- a/tavern/internal/c2/c2pb/c2_grpc.pb.go +++ b/tavern/internal/c2/c2pb/c2_grpc.pb.go @@ -24,6 +24,9 @@ const _ = grpc.SupportPackageIsVersion7 type C2Client interface { ClaimTasks(ctx context.Context, in *ClaimTasksRequest, opts ...grpc.CallOption) (*ClaimTasksResponse, error) ReportTaskOutput(ctx context.Context, in *ReportTaskOutputRequest, opts ...grpc.CallOption) (*ReportTaskOutputResponse, error) + // Report the active list of running processes. This list will replace any previously reported + // lists for the same host. + ReportProcessList(ctx context.Context, in *ReportProcessListRequest, opts ...grpc.CallOption) (*ReportProcessListResponse, error) // Download a file from the server, returning one or more chunks of data. // The maximum size of these chunks is determined by the server. // The server should reply with two headers: @@ -60,6 +63,15 @@ func (c *c2Client) ReportTaskOutput(ctx context.Context, in *ReportTaskOutputReq return out, nil } +func (c *c2Client) ReportProcessList(ctx context.Context, in *ReportProcessListRequest, opts ...grpc.CallOption) (*ReportProcessListResponse, error) { + out := new(ReportProcessListResponse) + err := c.cc.Invoke(ctx, "/c2.C2/ReportProcessList", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *c2Client) DownloadFile(ctx context.Context, in *DownloadFileRequest, opts ...grpc.CallOption) (C2_DownloadFileClient, error) { stream, err := c.cc.NewStream(ctx, &C2_ServiceDesc.Streams[0], "/c2.C2/DownloadFile", opts...) if err != nil { @@ -98,6 +110,9 @@ func (x *c2DownloadFileClient) Recv() (*DownloadFileResponse, error) { type C2Server interface { ClaimTasks(context.Context, *ClaimTasksRequest) (*ClaimTasksResponse, error) ReportTaskOutput(context.Context, *ReportTaskOutputRequest) (*ReportTaskOutputResponse, error) + // Report the active list of running processes. This list will replace any previously reported + // lists for the same host. + ReportProcessList(context.Context, *ReportProcessListRequest) (*ReportProcessListResponse, error) // Download a file from the server, returning one or more chunks of data. // The maximum size of these chunks is determined by the server. // The server should reply with two headers: @@ -119,6 +134,9 @@ func (UnimplementedC2Server) ClaimTasks(context.Context, *ClaimTasksRequest) (*C func (UnimplementedC2Server) ReportTaskOutput(context.Context, *ReportTaskOutputRequest) (*ReportTaskOutputResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ReportTaskOutput not implemented") } +func (UnimplementedC2Server) ReportProcessList(context.Context, *ReportProcessListRequest) (*ReportProcessListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ReportProcessList not implemented") +} func (UnimplementedC2Server) DownloadFile(*DownloadFileRequest, C2_DownloadFileServer) error { return status.Errorf(codes.Unimplemented, "method DownloadFile not implemented") } @@ -171,6 +189,24 @@ func _C2_ReportTaskOutput_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _C2_ReportProcessList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReportProcessListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(C2Server).ReportProcessList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/c2.C2/ReportProcessList", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(C2Server).ReportProcessList(ctx, req.(*ReportProcessListRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _C2_DownloadFile_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(DownloadFileRequest) if err := stream.RecvMsg(m); err != nil { @@ -207,6 +243,10 @@ var C2_ServiceDesc = grpc.ServiceDesc{ MethodName: "ReportTaskOutput", Handler: _C2_ReportTaskOutput_Handler, }, + { + MethodName: "ReportProcessList", + Handler: _C2_ReportProcessList_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/tavern/internal/ent/client.go b/tavern/internal/ent/client.go index 68f82957e..bede438eb 100644 --- a/tavern/internal/ent/client.go +++ b/tavern/internal/ent/client.go @@ -18,6 +18,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -36,6 +37,8 @@ type Client struct { File *FileClient // Host is the client for interacting with the Host builders. Host *HostClient + // Process is the client for interacting with the Process builders. + Process *ProcessClient // Quest is the client for interacting with the Quest builders. Quest *QuestClient // Tag is the client for interacting with the Tag builders. @@ -64,6 +67,7 @@ func (c *Client) init() { c.Beacon = NewBeaconClient(c.config) c.File = NewFileClient(c.config) c.Host = NewHostClient(c.config) + c.Process = NewProcessClient(c.config) c.Quest = NewQuestClient(c.config) c.Tag = NewTagClient(c.config) c.Task = NewTaskClient(c.config) @@ -152,16 +156,17 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := c.config cfg.driver = tx return &Tx{ - ctx: ctx, - config: cfg, - Beacon: NewBeaconClient(cfg), - File: NewFileClient(cfg), - Host: NewHostClient(cfg), - Quest: NewQuestClient(cfg), - Tag: NewTagClient(cfg), - Task: NewTaskClient(cfg), - Tome: NewTomeClient(cfg), - User: NewUserClient(cfg), + ctx: ctx, + config: cfg, + Beacon: NewBeaconClient(cfg), + File: NewFileClient(cfg), + Host: NewHostClient(cfg), + Process: NewProcessClient(cfg), + Quest: NewQuestClient(cfg), + Tag: NewTagClient(cfg), + Task: NewTaskClient(cfg), + Tome: NewTomeClient(cfg), + User: NewUserClient(cfg), }, nil } @@ -179,16 +184,17 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) cfg := c.config cfg.driver = &txDriver{tx: tx, drv: c.driver} return &Tx{ - ctx: ctx, - config: cfg, - Beacon: NewBeaconClient(cfg), - File: NewFileClient(cfg), - Host: NewHostClient(cfg), - Quest: NewQuestClient(cfg), - Tag: NewTagClient(cfg), - Task: NewTaskClient(cfg), - Tome: NewTomeClient(cfg), - User: NewUserClient(cfg), + ctx: ctx, + config: cfg, + Beacon: NewBeaconClient(cfg), + File: NewFileClient(cfg), + Host: NewHostClient(cfg), + Process: NewProcessClient(cfg), + Quest: NewQuestClient(cfg), + Tag: NewTagClient(cfg), + Task: NewTaskClient(cfg), + Tome: NewTomeClient(cfg), + User: NewUserClient(cfg), }, nil } @@ -218,7 +224,7 @@ func (c *Client) Close() error { // In order to add hooks to a specific client, call: `client.Node.Use(...)`. func (c *Client) Use(hooks ...Hook) { for _, n := range []interface{ Use(...Hook) }{ - c.Beacon, c.File, c.Host, c.Quest, c.Tag, c.Task, c.Tome, c.User, + c.Beacon, c.File, c.Host, c.Process, c.Quest, c.Tag, c.Task, c.Tome, c.User, } { n.Use(hooks...) } @@ -228,7 +234,7 @@ func (c *Client) Use(hooks ...Hook) { // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`. func (c *Client) Intercept(interceptors ...Interceptor) { for _, n := range []interface{ Intercept(...Interceptor) }{ - c.Beacon, c.File, c.Host, c.Quest, c.Tag, c.Task, c.Tome, c.User, + c.Beacon, c.File, c.Host, c.Process, c.Quest, c.Tag, c.Task, c.Tome, c.User, } { n.Intercept(interceptors...) } @@ -243,6 +249,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.File.mutate(ctx, m) case *HostMutation: return c.Host.mutate(ctx, m) + case *ProcessMutation: + return c.Process.mutate(ctx, m) case *QuestMutation: return c.Quest.mutate(ctx, m) case *TagMutation: @@ -738,6 +746,139 @@ func (c *HostClient) mutate(ctx context.Context, m *HostMutation) (Value, error) } } +// ProcessClient is a client for the Process schema. +type ProcessClient struct { + config +} + +// NewProcessClient returns a client for the Process from the given config. +func NewProcessClient(c config) *ProcessClient { + return &ProcessClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `process.Hooks(f(g(h())))`. +func (c *ProcessClient) Use(hooks ...Hook) { + c.hooks.Process = append(c.hooks.Process, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `process.Intercept(f(g(h())))`. +func (c *ProcessClient) Intercept(interceptors ...Interceptor) { + c.inters.Process = append(c.inters.Process, interceptors...) +} + +// Create returns a builder for creating a Process entity. +func (c *ProcessClient) Create() *ProcessCreate { + mutation := newProcessMutation(c.config, OpCreate) + return &ProcessCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Process entities. +func (c *ProcessClient) CreateBulk(builders ...*ProcessCreate) *ProcessCreateBulk { + return &ProcessCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *ProcessClient) MapCreateBulk(slice any, setFunc func(*ProcessCreate, int)) *ProcessCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &ProcessCreateBulk{err: fmt.Errorf("calling to ProcessClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*ProcessCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &ProcessCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Process. +func (c *ProcessClient) Update() *ProcessUpdate { + mutation := newProcessMutation(c.config, OpUpdate) + return &ProcessUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *ProcessClient) UpdateOne(pr *Process) *ProcessUpdateOne { + mutation := newProcessMutation(c.config, OpUpdateOne, withProcess(pr)) + return &ProcessUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *ProcessClient) UpdateOneID(id int) *ProcessUpdateOne { + mutation := newProcessMutation(c.config, OpUpdateOne, withProcessID(id)) + return &ProcessUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Process. +func (c *ProcessClient) Delete() *ProcessDelete { + mutation := newProcessMutation(c.config, OpDelete) + return &ProcessDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *ProcessClient) DeleteOne(pr *Process) *ProcessDeleteOne { + return c.DeleteOneID(pr.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *ProcessClient) DeleteOneID(id int) *ProcessDeleteOne { + builder := c.Delete().Where(process.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &ProcessDeleteOne{builder} +} + +// Query returns a query builder for Process. +func (c *ProcessClient) Query() *ProcessQuery { + return &ProcessQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeProcess}, + inters: c.Interceptors(), + } +} + +// Get returns a Process entity by its id. +func (c *ProcessClient) Get(ctx context.Context, id int) (*Process, error) { + return c.Query().Where(process.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *ProcessClient) GetX(ctx context.Context, id int) *Process { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *ProcessClient) Hooks() []Hook { + return c.hooks.Process +} + +// Interceptors returns the client interceptors. +func (c *ProcessClient) Interceptors() []Interceptor { + return c.inters.Process +} + +func (c *ProcessClient) mutate(ctx context.Context, m *ProcessMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&ProcessCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&ProcessUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&ProcessUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&ProcessDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown Process mutation op: %q", m.Op()) + } +} + // QuestClient is a client for the Quest schema. type QuestClient struct { config @@ -1224,6 +1365,22 @@ func (c *TaskClient) QueryBeacon(t *Task) *BeaconQuery { return query } +// QueryReportedProcesses queries the reported_processes edge of a Task. +func (c *TaskClient) QueryReportedProcesses(t *Task) *ProcessQuery { + query := (&ProcessClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := t.ID + step := sqlgraph.NewStep( + sqlgraph.From(task.Table, task.FieldID, id), + sqlgraph.To(process.Table, process.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, task.ReportedProcessesTable, task.ReportedProcessesColumn), + ) + fromV = sqlgraph.Neighbors(t.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *TaskClient) Hooks() []Hook { hooks := c.hooks.Task @@ -1536,9 +1693,9 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) // hooks and interceptors per client, for fast access. type ( hooks struct { - Beacon, File, Host, Quest, Tag, Task, Tome, User []ent.Hook + Beacon, File, Host, Process, Quest, Tag, Task, Tome, User []ent.Hook } inters struct { - Beacon, File, Host, Quest, Tag, Task, Tome, User []ent.Interceptor + Beacon, File, Host, Process, Quest, Tag, Task, Tome, User []ent.Interceptor } ) diff --git a/tavern/internal/ent/ent.go b/tavern/internal/ent/ent.go index 7a3addb51..30b545ce8 100644 --- a/tavern/internal/ent/ent.go +++ b/tavern/internal/ent/ent.go @@ -15,6 +15,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -80,14 +81,15 @@ var ( func checkColumn(table, column string) error { initCheck.Do(func() { columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ - beacon.Table: beacon.ValidColumn, - file.Table: file.ValidColumn, - host.Table: host.ValidColumn, - quest.Table: quest.ValidColumn, - tag.Table: tag.ValidColumn, - task.Table: task.ValidColumn, - tome.Table: tome.ValidColumn, - user.Table: user.ValidColumn, + beacon.Table: beacon.ValidColumn, + file.Table: file.ValidColumn, + host.Table: host.ValidColumn, + process.Table: process.ValidColumn, + quest.Table: quest.ValidColumn, + tag.Table: tag.ValidColumn, + task.Table: task.ValidColumn, + tome.Table: tome.ValidColumn, + user.Table: user.ValidColumn, }) }) return columnCheck(table, column) diff --git a/tavern/internal/ent/gql_collection.go b/tavern/internal/ent/gql_collection.go index b708cf6a4..0098cd5fa 100644 --- a/tavern/internal/ent/gql_collection.go +++ b/tavern/internal/ent/gql_collection.go @@ -11,6 +11,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -408,6 +409,83 @@ func newHostPaginateArgs(rv map[string]any) *hostPaginateArgs { return args } +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (pr *ProcessQuery) CollectFields(ctx context.Context, satisfies ...string) (*ProcessQuery, error) { + fc := graphql.GetFieldContext(ctx) + if fc == nil { + return pr, nil + } + if err := pr.collectField(ctx, graphql.GetOperationContext(ctx), fc.Field, nil, satisfies...); err != nil { + return nil, err + } + return pr, nil +} + +func (pr *ProcessQuery) collectField(ctx context.Context, opCtx *graphql.OperationContext, collected graphql.CollectedField, path []string, satisfies ...string) error { + path = append([]string(nil), path...) + var ( + unknownSeen bool + fieldSeen = make(map[string]struct{}, len(process.Columns)) + selectedFields = []string{process.FieldID} + ) + for _, field := range graphql.CollectFields(opCtx, collected.Selections, satisfies) { + switch field.Name { + case "pid": + if _, ok := fieldSeen[process.FieldPid]; !ok { + selectedFields = append(selectedFields, process.FieldPid) + fieldSeen[process.FieldPid] = struct{}{} + } + case "name": + if _, ok := fieldSeen[process.FieldName]; !ok { + selectedFields = append(selectedFields, process.FieldName) + fieldSeen[process.FieldName] = struct{}{} + } + case "principal": + if _, ok := fieldSeen[process.FieldPrincipal]; !ok { + selectedFields = append(selectedFields, process.FieldPrincipal) + fieldSeen[process.FieldPrincipal] = struct{}{} + } + case "id": + case "__typename": + default: + unknownSeen = true + } + } + if !unknownSeen { + pr.Select(selectedFields...) + } + return nil +} + +type processPaginateArgs struct { + first, last *int + after, before *Cursor + opts []ProcessPaginateOption +} + +func newProcessPaginateArgs(rv map[string]any) *processPaginateArgs { + args := &processPaginateArgs{} + if rv == nil { + return args + } + if v := rv[firstField]; v != nil { + args.first = v.(*int) + } + if v := rv[lastField]; v != nil { + args.last = v.(*int) + } + if v := rv[afterField]; v != nil { + args.after = v.(*Cursor) + } + if v := rv[beforeField]; v != nil { + args.before = v.(*Cursor) + } + if v, ok := rv[whereField].(*ProcessWhereInput); ok { + args.opts = append(args.opts, WithProcessFilter(v.Filter)) + } + return args +} + // CollectFields tells the query-builder to eagerly load connected nodes by resolver context. func (q *QuestQuery) CollectFields(ctx context.Context, satisfies ...string) (*QuestQuery, error) { fc := graphql.GetFieldContext(ctx) @@ -701,6 +779,18 @@ func (t *TaskQuery) collectField(ctx context.Context, opCtx *graphql.OperationCo return err } t.withBeacon = query + case "reportedProcesses": + var ( + alias = field.Alias + path = append(path, alias) + query = (&ProcessClient{config: t.config}).Query() + ) + if err := query.collectField(ctx, opCtx, field, path, satisfies...); err != nil { + return err + } + t.WithNamedReportedProcesses(alias, func(wq *ProcessQuery) { + *wq = *query + }) case "createdAt": if _, ok := fieldSeen[task.FieldCreatedAt]; !ok { selectedFields = append(selectedFields, task.FieldCreatedAt) diff --git a/tavern/internal/ent/gql_edge.go b/tavern/internal/ent/gql_edge.go index baeeb612e..e39fab3dc 100644 --- a/tavern/internal/ent/gql_edge.go +++ b/tavern/internal/ent/gql_edge.go @@ -128,6 +128,18 @@ func (t *Task) Beacon(ctx context.Context) (*Beacon, error) { return result, err } +func (t *Task) ReportedProcesses(ctx context.Context) (result []*Process, err error) { + if fc := graphql.GetFieldContext(ctx); fc != nil && fc.Field.Alias != "" { + result, err = t.NamedReportedProcesses(graphql.GetFieldContext(ctx).Field.Alias) + } else { + result, err = t.Edges.ReportedProcessesOrErr() + } + if IsNotLoaded(err) { + result, err = t.QueryReportedProcesses().All(ctx) + } + return result, err +} + func (t *Tome) Files(ctx context.Context) (result []*File, err error) { if fc := graphql.GetFieldContext(ctx); fc != nil && fc.Field.Alias != "" { result, err = t.NamedFiles(graphql.GetFieldContext(ctx).Field.Alias) diff --git a/tavern/internal/ent/gql_node.go b/tavern/internal/ent/gql_node.go index c2cf45176..0ee9cc249 100644 --- a/tavern/internal/ent/gql_node.go +++ b/tavern/internal/ent/gql_node.go @@ -18,6 +18,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -39,6 +40,9 @@ func (n *File) IsNode() {} // IsNode implements the Node interface check for GQLGen. func (n *Host) IsNode() {} +// IsNode implements the Node interface check for GQLGen. +func (n *Process) IsNode() {} + // IsNode implements the Node interface check for GQLGen. func (n *Quest) IsNode() {} @@ -148,6 +152,18 @@ func (c *Client) noder(ctx context.Context, table string, id int) (Noder, error) return nil, err } return n, nil + case process.Table: + query := c.Process.Query(). + Where(process.ID(id)) + query, err := query.CollectFields(ctx, "Process") + if err != nil { + return nil, err + } + n, err := query.Only(ctx) + if err != nil { + return nil, err + } + return n, nil case quest.Table: query := c.Quest.Query(). Where(quest.ID(id)) @@ -329,6 +345,22 @@ func (c *Client) noders(ctx context.Context, table string, ids []int) ([]Noder, *noder = node } } + case process.Table: + query := c.Process.Query(). + Where(process.IDIn(ids...)) + query, err := query.CollectFields(ctx, "Process") + if err != nil { + return nil, err + } + nodes, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } case quest.Table: query := c.Quest.Query(). Where(quest.IDIn(ids...)) diff --git a/tavern/internal/ent/gql_pagination.go b/tavern/internal/ent/gql_pagination.go index 50196d99b..d10ce0187 100644 --- a/tavern/internal/ent/gql_pagination.go +++ b/tavern/internal/ent/gql_pagination.go @@ -18,6 +18,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -1056,6 +1057,252 @@ func (h *Host) ToEdge(order *HostOrder) *HostEdge { } } +// ProcessEdge is the edge representation of Process. +type ProcessEdge struct { + Node *Process `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// ProcessConnection is the connection containing edges to Process. +type ProcessConnection struct { + Edges []*ProcessEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +func (c *ProcessConnection) build(nodes []*Process, pager *processPager, after *Cursor, first *int, before *Cursor, last *int) { + c.PageInfo.HasNextPage = before != nil + c.PageInfo.HasPreviousPage = after != nil + if first != nil && *first+1 == len(nodes) { + c.PageInfo.HasNextPage = true + nodes = nodes[:len(nodes)-1] + } else if last != nil && *last+1 == len(nodes) { + c.PageInfo.HasPreviousPage = true + nodes = nodes[:len(nodes)-1] + } + var nodeAt func(int) *Process + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *Process { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *Process { + return nodes[i] + } + } + c.Edges = make([]*ProcessEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + c.Edges[i] = &ProcessEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + if l := len(c.Edges); l > 0 { + c.PageInfo.StartCursor = &c.Edges[0].Cursor + c.PageInfo.EndCursor = &c.Edges[l-1].Cursor + } + if c.TotalCount == 0 { + c.TotalCount = len(nodes) + } +} + +// ProcessPaginateOption enables pagination customization. +type ProcessPaginateOption func(*processPager) error + +// WithProcessOrder configures pagination ordering. +func WithProcessOrder(order *ProcessOrder) ProcessPaginateOption { + if order == nil { + order = DefaultProcessOrder + } + o := *order + return func(pager *processPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultProcessOrder.Field + } + pager.order = &o + return nil + } +} + +// WithProcessFilter configures pagination filter. +func WithProcessFilter(filter func(*ProcessQuery) (*ProcessQuery, error)) ProcessPaginateOption { + return func(pager *processPager) error { + if filter == nil { + return errors.New("ProcessQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type processPager struct { + reverse bool + order *ProcessOrder + filter func(*ProcessQuery) (*ProcessQuery, error) +} + +func newProcessPager(opts []ProcessPaginateOption, reverse bool) (*processPager, error) { + pager := &processPager{reverse: reverse} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultProcessOrder + } + return pager, nil +} + +func (p *processPager) applyFilter(query *ProcessQuery) (*ProcessQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *processPager) toCursor(pr *Process) Cursor { + return p.order.Field.toCursor(pr) +} + +func (p *processPager) applyCursors(query *ProcessQuery, after, before *Cursor) (*ProcessQuery, error) { + direction := p.order.Direction + if p.reverse { + direction = direction.Reverse() + } + for _, predicate := range entgql.CursorsPredicate(after, before, DefaultProcessOrder.Field.column, p.order.Field.column, direction) { + query = query.Where(predicate) + } + return query, nil +} + +func (p *processPager) applyOrder(query *ProcessQuery) *ProcessQuery { + direction := p.order.Direction + if p.reverse { + direction = direction.Reverse() + } + query = query.Order(p.order.Field.toTerm(direction.OrderTermOption())) + if p.order.Field != DefaultProcessOrder.Field { + query = query.Order(DefaultProcessOrder.Field.toTerm(direction.OrderTermOption())) + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(p.order.Field.column) + } + return query +} + +func (p *processPager) orderExpr(query *ProcessQuery) sql.Querier { + direction := p.order.Direction + if p.reverse { + direction = direction.Reverse() + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(p.order.Field.column) + } + return sql.ExprFunc(func(b *sql.Builder) { + b.Ident(p.order.Field.column).Pad().WriteString(string(direction)) + if p.order.Field != DefaultProcessOrder.Field { + b.Comma().Ident(DefaultProcessOrder.Field.column).Pad().WriteString(string(direction)) + } + }) +} + +// Paginate executes the query and returns a relay based cursor connection to Process. +func (pr *ProcessQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...ProcessPaginateOption, +) (*ProcessConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newProcessPager(opts, last != nil) + if err != nil { + return nil, err + } + if pr, err = pager.applyFilter(pr); err != nil { + return nil, err + } + conn := &ProcessConnection{Edges: []*ProcessEdge{}} + ignoredEdges := !hasCollectedField(ctx, edgesField) + if hasCollectedField(ctx, totalCountField) || hasCollectedField(ctx, pageInfoField) { + hasPagination := after != nil || first != nil || before != nil || last != nil + if hasPagination || ignoredEdges { + if conn.TotalCount, err = pr.Clone().Count(ctx); err != nil { + return nil, err + } + conn.PageInfo.HasNextPage = first != nil && conn.TotalCount > 0 + conn.PageInfo.HasPreviousPage = last != nil && conn.TotalCount > 0 + } + } + if ignoredEdges || (first != nil && *first == 0) || (last != nil && *last == 0) { + return conn, nil + } + if pr, err = pager.applyCursors(pr, after, before); err != nil { + return nil, err + } + if limit := paginateLimit(first, last); limit != 0 { + pr.Limit(limit) + } + if field := collectedField(ctx, edgesField, nodeField); field != nil { + if err := pr.collectField(ctx, graphql.GetOperationContext(ctx), *field, []string{edgesField, nodeField}); err != nil { + return nil, err + } + } + pr = pager.applyOrder(pr) + nodes, err := pr.All(ctx) + if err != nil { + return nil, err + } + conn.build(nodes, pager, after, first, before, last) + return conn, nil +} + +// ProcessOrderField defines the ordering field of Process. +type ProcessOrderField struct { + // Value extracts the ordering value from the given Process. + Value func(*Process) (ent.Value, error) + column string // field or computed. + toTerm func(...sql.OrderTermOption) process.OrderOption + toCursor func(*Process) Cursor +} + +// ProcessOrder defines the ordering of Process. +type ProcessOrder struct { + Direction OrderDirection `json:"direction"` + Field *ProcessOrderField `json:"field"` +} + +// DefaultProcessOrder is the default ordering of Process. +var DefaultProcessOrder = &ProcessOrder{ + Direction: entgql.OrderDirectionAsc, + Field: &ProcessOrderField{ + Value: func(pr *Process) (ent.Value, error) { + return pr.ID, nil + }, + column: process.FieldID, + toTerm: process.ByID, + toCursor: func(pr *Process) Cursor { + return Cursor{ID: pr.ID} + }, + }, +} + +// ToEdge converts Process into ProcessEdge. +func (pr *Process) ToEdge(order *ProcessOrder) *ProcessEdge { + if order == nil { + order = DefaultProcessOrder + } + return &ProcessEdge{ + Node: pr, + Cursor: order.Field.toCursor(pr), + } +} + // QuestEdge is the edge representation of Quest. type QuestEdge struct { Node *Quest `json:"node"` diff --git a/tavern/internal/ent/gql_where_input.go b/tavern/internal/ent/gql_where_input.go index a960260f6..6cd226237 100644 --- a/tavern/internal/ent/gql_where_input.go +++ b/tavern/internal/ent/gql_where_input.go @@ -11,6 +11,7 @@ import ( "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -1264,6 +1265,272 @@ func (i *HostWhereInput) P() (predicate.Host, error) { } } +// ProcessWhereInput represents a where input for filtering Process queries. +type ProcessWhereInput struct { + Predicates []predicate.Process `json:"-"` + Not *ProcessWhereInput `json:"not,omitempty"` + Or []*ProcessWhereInput `json:"or,omitempty"` + And []*ProcessWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "pid" field predicates. + Pid *uint64 `json:"pid,omitempty"` + PidNEQ *uint64 `json:"pidNEQ,omitempty"` + PidIn []uint64 `json:"pidIn,omitempty"` + PidNotIn []uint64 `json:"pidNotIn,omitempty"` + PidGT *uint64 `json:"pidGT,omitempty"` + PidGTE *uint64 `json:"pidGTE,omitempty"` + PidLT *uint64 `json:"pidLT,omitempty"` + PidLTE *uint64 `json:"pidLTE,omitempty"` + + // "name" field predicates. + Name *string `json:"name,omitempty"` + NameNEQ *string `json:"nameNEQ,omitempty"` + NameIn []string `json:"nameIn,omitempty"` + NameNotIn []string `json:"nameNotIn,omitempty"` + NameGT *string `json:"nameGT,omitempty"` + NameGTE *string `json:"nameGTE,omitempty"` + NameLT *string `json:"nameLT,omitempty"` + NameLTE *string `json:"nameLTE,omitempty"` + NameContains *string `json:"nameContains,omitempty"` + NameHasPrefix *string `json:"nameHasPrefix,omitempty"` + NameHasSuffix *string `json:"nameHasSuffix,omitempty"` + NameEqualFold *string `json:"nameEqualFold,omitempty"` + NameContainsFold *string `json:"nameContainsFold,omitempty"` + + // "principal" field predicates. + Principal *string `json:"principal,omitempty"` + PrincipalNEQ *string `json:"principalNEQ,omitempty"` + PrincipalIn []string `json:"principalIn,omitempty"` + PrincipalNotIn []string `json:"principalNotIn,omitempty"` + PrincipalGT *string `json:"principalGT,omitempty"` + PrincipalGTE *string `json:"principalGTE,omitempty"` + PrincipalLT *string `json:"principalLT,omitempty"` + PrincipalLTE *string `json:"principalLTE,omitempty"` + PrincipalContains *string `json:"principalContains,omitempty"` + PrincipalHasPrefix *string `json:"principalHasPrefix,omitempty"` + PrincipalHasSuffix *string `json:"principalHasSuffix,omitempty"` + PrincipalEqualFold *string `json:"principalEqualFold,omitempty"` + PrincipalContainsFold *string `json:"principalContainsFold,omitempty"` +} + +// AddPredicates adds custom predicates to the where input to be used during the filtering phase. +func (i *ProcessWhereInput) AddPredicates(predicates ...predicate.Process) { + i.Predicates = append(i.Predicates, predicates...) +} + +// Filter applies the ProcessWhereInput filter on the ProcessQuery builder. +func (i *ProcessWhereInput) Filter(q *ProcessQuery) (*ProcessQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + if err == ErrEmptyProcessWhereInput { + return q, nil + } + return nil, err + } + return q.Where(p), nil +} + +// ErrEmptyProcessWhereInput is returned in case the ProcessWhereInput is empty. +var ErrEmptyProcessWhereInput = errors.New("ent: empty predicate ProcessWhereInput") + +// P returns a predicate for filtering processes. +// An error is returned if the input is empty or invalid. +func (i *ProcessWhereInput) P() (predicate.Process, error) { + var predicates []predicate.Process + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'not'", err) + } + predicates = append(predicates, process.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, fmt.Errorf("%w: field 'or'", err) + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.Process, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'or'", err) + } + or = append(or, p) + } + predicates = append(predicates, process.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, fmt.Errorf("%w: field 'and'", err) + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.Process, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'and'", err) + } + and = append(and, p) + } + predicates = append(predicates, process.And(and...)) + } + predicates = append(predicates, i.Predicates...) + if i.ID != nil { + predicates = append(predicates, process.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, process.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, process.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, process.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, process.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, process.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, process.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, process.IDLTE(*i.IDLTE)) + } + if i.Pid != nil { + predicates = append(predicates, process.PidEQ(*i.Pid)) + } + if i.PidNEQ != nil { + predicates = append(predicates, process.PidNEQ(*i.PidNEQ)) + } + if len(i.PidIn) > 0 { + predicates = append(predicates, process.PidIn(i.PidIn...)) + } + if len(i.PidNotIn) > 0 { + predicates = append(predicates, process.PidNotIn(i.PidNotIn...)) + } + if i.PidGT != nil { + predicates = append(predicates, process.PidGT(*i.PidGT)) + } + if i.PidGTE != nil { + predicates = append(predicates, process.PidGTE(*i.PidGTE)) + } + if i.PidLT != nil { + predicates = append(predicates, process.PidLT(*i.PidLT)) + } + if i.PidLTE != nil { + predicates = append(predicates, process.PidLTE(*i.PidLTE)) + } + if i.Name != nil { + predicates = append(predicates, process.NameEQ(*i.Name)) + } + if i.NameNEQ != nil { + predicates = append(predicates, process.NameNEQ(*i.NameNEQ)) + } + if len(i.NameIn) > 0 { + predicates = append(predicates, process.NameIn(i.NameIn...)) + } + if len(i.NameNotIn) > 0 { + predicates = append(predicates, process.NameNotIn(i.NameNotIn...)) + } + if i.NameGT != nil { + predicates = append(predicates, process.NameGT(*i.NameGT)) + } + if i.NameGTE != nil { + predicates = append(predicates, process.NameGTE(*i.NameGTE)) + } + if i.NameLT != nil { + predicates = append(predicates, process.NameLT(*i.NameLT)) + } + if i.NameLTE != nil { + predicates = append(predicates, process.NameLTE(*i.NameLTE)) + } + if i.NameContains != nil { + predicates = append(predicates, process.NameContains(*i.NameContains)) + } + if i.NameHasPrefix != nil { + predicates = append(predicates, process.NameHasPrefix(*i.NameHasPrefix)) + } + if i.NameHasSuffix != nil { + predicates = append(predicates, process.NameHasSuffix(*i.NameHasSuffix)) + } + if i.NameEqualFold != nil { + predicates = append(predicates, process.NameEqualFold(*i.NameEqualFold)) + } + if i.NameContainsFold != nil { + predicates = append(predicates, process.NameContainsFold(*i.NameContainsFold)) + } + if i.Principal != nil { + predicates = append(predicates, process.PrincipalEQ(*i.Principal)) + } + if i.PrincipalNEQ != nil { + predicates = append(predicates, process.PrincipalNEQ(*i.PrincipalNEQ)) + } + if len(i.PrincipalIn) > 0 { + predicates = append(predicates, process.PrincipalIn(i.PrincipalIn...)) + } + if len(i.PrincipalNotIn) > 0 { + predicates = append(predicates, process.PrincipalNotIn(i.PrincipalNotIn...)) + } + if i.PrincipalGT != nil { + predicates = append(predicates, process.PrincipalGT(*i.PrincipalGT)) + } + if i.PrincipalGTE != nil { + predicates = append(predicates, process.PrincipalGTE(*i.PrincipalGTE)) + } + if i.PrincipalLT != nil { + predicates = append(predicates, process.PrincipalLT(*i.PrincipalLT)) + } + if i.PrincipalLTE != nil { + predicates = append(predicates, process.PrincipalLTE(*i.PrincipalLTE)) + } + if i.PrincipalContains != nil { + predicates = append(predicates, process.PrincipalContains(*i.PrincipalContains)) + } + if i.PrincipalHasPrefix != nil { + predicates = append(predicates, process.PrincipalHasPrefix(*i.PrincipalHasPrefix)) + } + if i.PrincipalHasSuffix != nil { + predicates = append(predicates, process.PrincipalHasSuffix(*i.PrincipalHasSuffix)) + } + if i.PrincipalEqualFold != nil { + predicates = append(predicates, process.PrincipalEqualFold(*i.PrincipalEqualFold)) + } + if i.PrincipalContainsFold != nil { + predicates = append(predicates, process.PrincipalContainsFold(*i.PrincipalContainsFold)) + } + + switch len(predicates) { + case 0: + return nil, ErrEmptyProcessWhereInput + case 1: + return predicates[0], nil + default: + return process.And(predicates...), nil + } +} + // QuestWhereInput represents a where input for filtering Quest queries. type QuestWhereInput struct { Predicates []predicate.Quest `json:"-"` @@ -2002,6 +2269,10 @@ type TaskWhereInput struct { // "beacon" edge predicates. HasBeacon *bool `json:"hasBeacon,omitempty"` HasBeaconWith []*BeaconWhereInput `json:"hasBeaconWith,omitempty"` + + // "reported_processes" edge predicates. + HasReportedProcesses *bool `json:"hasReportedProcesses,omitempty"` + HasReportedProcessesWith []*ProcessWhereInput `json:"hasReportedProcessesWith,omitempty"` } // AddPredicates adds custom predicates to the where input to be used during the filtering phase. @@ -2388,6 +2659,24 @@ func (i *TaskWhereInput) P() (predicate.Task, error) { } predicates = append(predicates, task.HasBeaconWith(with...)) } + if i.HasReportedProcesses != nil { + p := task.HasReportedProcesses() + if !*i.HasReportedProcesses { + p = task.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasReportedProcessesWith) > 0 { + with := make([]predicate.Process, 0, len(i.HasReportedProcessesWith)) + for _, w := range i.HasReportedProcessesWith { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'HasReportedProcessesWith'", err) + } + with = append(with, p) + } + predicates = append(predicates, task.HasReportedProcessesWith(with...)) + } switch len(predicates) { case 0: return nil, ErrEmptyTaskWhereInput diff --git a/tavern/internal/ent/hook/hook.go b/tavern/internal/ent/hook/hook.go index 81e30def7..78bbb85ea 100644 --- a/tavern/internal/ent/hook/hook.go +++ b/tavern/internal/ent/hook/hook.go @@ -45,6 +45,18 @@ func (f HostFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.HostMutation", m) } +// The ProcessFunc type is an adapter to allow the use of ordinary +// function as Process mutator. +type ProcessFunc func(context.Context, *ent.ProcessMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f ProcessFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.ProcessMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.ProcessMutation", m) +} + // The QuestFunc type is an adapter to allow the use of ordinary // function as Quest mutator. type QuestFunc func(context.Context, *ent.QuestMutation) (ent.Value, error) diff --git a/tavern/internal/ent/migrate/schema.go b/tavern/internal/ent/migrate/schema.go index e24e26468..070589e19 100644 --- a/tavern/internal/ent/migrate/schema.go +++ b/tavern/internal/ent/migrate/schema.go @@ -64,6 +64,28 @@ var ( Columns: HostsColumns, PrimaryKey: []*schema.Column{HostsColumns[0]}, } + // ProcessesColumns holds the columns for the "processes" table. + ProcessesColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "pid", Type: field.TypeUint64}, + {Name: "name", Type: field.TypeString}, + {Name: "principal", Type: field.TypeString}, + {Name: "task_reported_processes", Type: field.TypeInt, Nullable: true}, + } + // ProcessesTable holds the schema information for the "processes" table. + ProcessesTable = &schema.Table{ + Name: "processes", + Columns: ProcessesColumns, + PrimaryKey: []*schema.Column{ProcessesColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "processes_tasks_reported_processes", + Columns: []*schema.Column{ProcessesColumns[4]}, + RefColumns: []*schema.Column{TasksColumns[0]}, + OnDelete: schema.SetNull, + }, + }, + } // QuestsColumns holds the columns for the "quests" table. QuestsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -235,6 +257,7 @@ var ( BeaconsTable, FilesTable, HostsTable, + ProcessesTable, QuestsTable, TagsTable, TasksTable, @@ -247,6 +270,7 @@ var ( func init() { BeaconsTable.ForeignKeys[0].RefTable = HostsTable + ProcessesTable.ForeignKeys[0].RefTable = TasksTable QuestsTable.ForeignKeys[0].RefTable = TomesTable QuestsTable.ForeignKeys[1].RefTable = FilesTable QuestsTable.ForeignKeys[2].RefTable = UsersTable diff --git a/tavern/internal/ent/mutation.go b/tavern/internal/ent/mutation.go index 5b39b4e24..71f3cb09e 100644 --- a/tavern/internal/ent/mutation.go +++ b/tavern/internal/ent/mutation.go @@ -15,6 +15,7 @@ import ( "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/tag" "realm.pub/tavern/internal/ent/task" @@ -31,14 +32,15 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. - TypeBeacon = "Beacon" - TypeFile = "File" - TypeHost = "Host" - TypeQuest = "Quest" - TypeTag = "Tag" - TypeTask = "Task" - TypeTome = "Tome" - TypeUser = "User" + TypeBeacon = "Beacon" + TypeFile = "File" + TypeHost = "Host" + TypeProcess = "Process" + TypeQuest = "Quest" + TypeTag = "Tag" + TypeTask = "Task" + TypeTome = "Tome" + TypeUser = "User" ) // BeaconMutation represents an operation that mutates the Beacon nodes in the graph. @@ -2408,6 +2410,476 @@ func (m *HostMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Host edge %s", name) } +// ProcessMutation represents an operation that mutates the Process nodes in the graph. +type ProcessMutation struct { + config + op Op + typ string + id *int + pid *uint64 + addpid *int64 + name *string + principal *string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*Process, error) + predicates []predicate.Process +} + +var _ ent.Mutation = (*ProcessMutation)(nil) + +// processOption allows management of the mutation configuration using functional options. +type processOption func(*ProcessMutation) + +// newProcessMutation creates new mutation for the Process entity. +func newProcessMutation(c config, op Op, opts ...processOption) *ProcessMutation { + m := &ProcessMutation{ + config: c, + op: op, + typ: TypeProcess, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withProcessID sets the ID field of the mutation. +func withProcessID(id int) processOption { + return func(m *ProcessMutation) { + var ( + err error + once sync.Once + value *Process + ) + m.oldValue = func(ctx context.Context) (*Process, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Process.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withProcess sets the old Process of the mutation. +func withProcess(node *Process) processOption { + return func(m *ProcessMutation) { + m.oldValue = func(context.Context) (*Process, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m ProcessMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m ProcessMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *ProcessMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *ProcessMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Process.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetPid sets the "pid" field. +func (m *ProcessMutation) SetPid(u uint64) { + m.pid = &u + m.addpid = nil +} + +// Pid returns the value of the "pid" field in the mutation. +func (m *ProcessMutation) Pid() (r uint64, exists bool) { + v := m.pid + if v == nil { + return + } + return *v, true +} + +// OldPid returns the old "pid" field's value of the Process entity. +// If the Process object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProcessMutation) OldPid(ctx context.Context) (v uint64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPid is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPid requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPid: %w", err) + } + return oldValue.Pid, nil +} + +// AddPid adds u to the "pid" field. +func (m *ProcessMutation) AddPid(u int64) { + if m.addpid != nil { + *m.addpid += u + } else { + m.addpid = &u + } +} + +// AddedPid returns the value that was added to the "pid" field in this mutation. +func (m *ProcessMutation) AddedPid() (r int64, exists bool) { + v := m.addpid + if v == nil { + return + } + return *v, true +} + +// ResetPid resets all changes to the "pid" field. +func (m *ProcessMutation) ResetPid() { + m.pid = nil + m.addpid = nil +} + +// SetName sets the "name" field. +func (m *ProcessMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *ProcessMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the Process entity. +// If the Process object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProcessMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *ProcessMutation) ResetName() { + m.name = nil +} + +// SetPrincipal sets the "principal" field. +func (m *ProcessMutation) SetPrincipal(s string) { + m.principal = &s +} + +// Principal returns the value of the "principal" field in the mutation. +func (m *ProcessMutation) Principal() (r string, exists bool) { + v := m.principal + if v == nil { + return + } + return *v, true +} + +// OldPrincipal returns the old "principal" field's value of the Process entity. +// If the Process object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProcessMutation) OldPrincipal(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPrincipal is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPrincipal requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPrincipal: %w", err) + } + return oldValue.Principal, nil +} + +// ResetPrincipal resets all changes to the "principal" field. +func (m *ProcessMutation) ResetPrincipal() { + m.principal = nil +} + +// Where appends a list predicates to the ProcessMutation builder. +func (m *ProcessMutation) Where(ps ...predicate.Process) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the ProcessMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *ProcessMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.Process, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *ProcessMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *ProcessMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (Process). +func (m *ProcessMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *ProcessMutation) Fields() []string { + fields := make([]string, 0, 3) + if m.pid != nil { + fields = append(fields, process.FieldPid) + } + if m.name != nil { + fields = append(fields, process.FieldName) + } + if m.principal != nil { + fields = append(fields, process.FieldPrincipal) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *ProcessMutation) Field(name string) (ent.Value, bool) { + switch name { + case process.FieldPid: + return m.Pid() + case process.FieldName: + return m.Name() + case process.FieldPrincipal: + return m.Principal() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *ProcessMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case process.FieldPid: + return m.OldPid(ctx) + case process.FieldName: + return m.OldName(ctx) + case process.FieldPrincipal: + return m.OldPrincipal(ctx) + } + return nil, fmt.Errorf("unknown Process field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ProcessMutation) SetField(name string, value ent.Value) error { + switch name { + case process.FieldPid: + v, ok := value.(uint64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPid(v) + return nil + case process.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case process.FieldPrincipal: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPrincipal(v) + return nil + } + return fmt.Errorf("unknown Process field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *ProcessMutation) AddedFields() []string { + var fields []string + if m.addpid != nil { + fields = append(fields, process.FieldPid) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *ProcessMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case process.FieldPid: + return m.AddedPid() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *ProcessMutation) AddField(name string, value ent.Value) error { + switch name { + case process.FieldPid: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddPid(v) + return nil + } + return fmt.Errorf("unknown Process numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *ProcessMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *ProcessMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *ProcessMutation) ClearField(name string) error { + return fmt.Errorf("unknown Process nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *ProcessMutation) ResetField(name string) error { + switch name { + case process.FieldPid: + m.ResetPid() + return nil + case process.FieldName: + m.ResetName() + return nil + case process.FieldPrincipal: + m.ResetPrincipal() + return nil + } + return fmt.Errorf("unknown Process field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *ProcessMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *ProcessMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *ProcessMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *ProcessMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *ProcessMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *ProcessMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *ProcessMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown Process unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *ProcessMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown Process edge %s", name) +} + // QuestMutation represents an operation that mutates the Quest nodes in the graph. type QuestMutation struct { config @@ -3664,26 +4136,29 @@ func (m *TagMutation) ResetEdge(name string) error { // TaskMutation represents an operation that mutates the Task nodes in the graph. type TaskMutation struct { config - op Op - typ string - id *int - created_at *time.Time - last_modified_at *time.Time - claimed_at *time.Time - exec_started_at *time.Time - exec_finished_at *time.Time - output *string - output_size *int - addoutput_size *int - error *string - clearedFields map[string]struct{} - quest *int - clearedquest bool - beacon *int - clearedbeacon bool - done bool - oldValue func(context.Context) (*Task, error) - predicates []predicate.Task + op Op + typ string + id *int + created_at *time.Time + last_modified_at *time.Time + claimed_at *time.Time + exec_started_at *time.Time + exec_finished_at *time.Time + output *string + output_size *int + addoutput_size *int + error *string + clearedFields map[string]struct{} + quest *int + clearedquest bool + beacon *int + clearedbeacon bool + reported_processes map[int]struct{} + removedreported_processes map[int]struct{} + clearedreported_processes bool + done bool + oldValue func(context.Context) (*Task, error) + predicates []predicate.Task } var _ ent.Mutation = (*TaskMutation)(nil) @@ -4235,6 +4710,60 @@ func (m *TaskMutation) ResetBeacon() { m.clearedbeacon = false } +// AddReportedProcessIDs adds the "reported_processes" edge to the Process entity by ids. +func (m *TaskMutation) AddReportedProcessIDs(ids ...int) { + if m.reported_processes == nil { + m.reported_processes = make(map[int]struct{}) + } + for i := range ids { + m.reported_processes[ids[i]] = struct{}{} + } +} + +// ClearReportedProcesses clears the "reported_processes" edge to the Process entity. +func (m *TaskMutation) ClearReportedProcesses() { + m.clearedreported_processes = true +} + +// ReportedProcessesCleared reports if the "reported_processes" edge to the Process entity was cleared. +func (m *TaskMutation) ReportedProcessesCleared() bool { + return m.clearedreported_processes +} + +// RemoveReportedProcessIDs removes the "reported_processes" edge to the Process entity by IDs. +func (m *TaskMutation) RemoveReportedProcessIDs(ids ...int) { + if m.removedreported_processes == nil { + m.removedreported_processes = make(map[int]struct{}) + } + for i := range ids { + delete(m.reported_processes, ids[i]) + m.removedreported_processes[ids[i]] = struct{}{} + } +} + +// RemovedReportedProcesses returns the removed IDs of the "reported_processes" edge to the Process entity. +func (m *TaskMutation) RemovedReportedProcessesIDs() (ids []int) { + for id := range m.removedreported_processes { + ids = append(ids, id) + } + return +} + +// ReportedProcessesIDs returns the "reported_processes" edge IDs in the mutation. +func (m *TaskMutation) ReportedProcessesIDs() (ids []int) { + for id := range m.reported_processes { + ids = append(ids, id) + } + return +} + +// ResetReportedProcesses resets all changes to the "reported_processes" edge. +func (m *TaskMutation) ResetReportedProcesses() { + m.reported_processes = nil + m.clearedreported_processes = false + m.removedreported_processes = nil +} + // Where appends a list predicates to the TaskMutation builder. func (m *TaskMutation) Where(ps ...predicate.Task) { m.predicates = append(m.predicates, ps...) @@ -4535,13 +5064,16 @@ func (m *TaskMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *TaskMutation) AddedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.quest != nil { edges = append(edges, task.EdgeQuest) } if m.beacon != nil { edges = append(edges, task.EdgeBeacon) } + if m.reported_processes != nil { + edges = append(edges, task.EdgeReportedProcesses) + } return edges } @@ -4557,31 +5089,51 @@ func (m *TaskMutation) AddedIDs(name string) []ent.Value { if id := m.beacon; id != nil { return []ent.Value{*id} } + case task.EdgeReportedProcesses: + ids := make([]ent.Value, 0, len(m.reported_processes)) + for id := range m.reported_processes { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *TaskMutation) RemovedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) + if m.removedreported_processes != nil { + edges = append(edges, task.EdgeReportedProcesses) + } return edges } // RemovedIDs returns all IDs (to other nodes) that were removed for the edge with // the given name in this mutation. func (m *TaskMutation) RemovedIDs(name string) []ent.Value { + switch name { + case task.EdgeReportedProcesses: + ids := make([]ent.Value, 0, len(m.removedreported_processes)) + for id := range m.removedreported_processes { + ids = append(ids, id) + } + return ids + } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *TaskMutation) ClearedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.clearedquest { edges = append(edges, task.EdgeQuest) } if m.clearedbeacon { edges = append(edges, task.EdgeBeacon) } + if m.clearedreported_processes { + edges = append(edges, task.EdgeReportedProcesses) + } return edges } @@ -4593,6 +5145,8 @@ func (m *TaskMutation) EdgeCleared(name string) bool { return m.clearedquest case task.EdgeBeacon: return m.clearedbeacon + case task.EdgeReportedProcesses: + return m.clearedreported_processes } return false } @@ -4621,6 +5175,9 @@ func (m *TaskMutation) ResetEdge(name string) error { case task.EdgeBeacon: m.ResetBeacon() return nil + case task.EdgeReportedProcesses: + m.ResetReportedProcesses() + return nil } return fmt.Errorf("unknown Task edge %s", name) } diff --git a/tavern/internal/ent/predicate/predicate.go b/tavern/internal/ent/predicate/predicate.go index 4b796a209..8b3923f42 100644 --- a/tavern/internal/ent/predicate/predicate.go +++ b/tavern/internal/ent/predicate/predicate.go @@ -15,6 +15,9 @@ type File func(*sql.Selector) // Host is the predicate function for host builders. type Host func(*sql.Selector) +// Process is the predicate function for process builders. +type Process func(*sql.Selector) + // Quest is the predicate function for quest builders. type Quest func(*sql.Selector) diff --git a/tavern/internal/ent/privacy/privacy.go b/tavern/internal/ent/privacy/privacy.go index 81ac66536..acb3a2e64 100644 --- a/tavern/internal/ent/privacy/privacy.go +++ b/tavern/internal/ent/privacy/privacy.go @@ -182,6 +182,30 @@ func (f HostMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.HostMutation", m) } +// The ProcessQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type ProcessQueryRuleFunc func(context.Context, *ent.ProcessQuery) error + +// EvalQuery return f(ctx, q). +func (f ProcessQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.ProcessQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.ProcessQuery", q) +} + +// The ProcessMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type ProcessMutationRuleFunc func(context.Context, *ent.ProcessMutation) error + +// EvalMutation calls f(ctx, m). +func (f ProcessMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.ProcessMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.ProcessMutation", m) +} + // The QuestQueryRuleFunc type is an adapter to allow the use of ordinary // functions as a query rule. type QuestQueryRuleFunc func(context.Context, *ent.QuestQuery) error diff --git a/tavern/internal/ent/process.go b/tavern/internal/ent/process.go new file mode 100644 index 000000000..47707f078 --- /dev/null +++ b/tavern/internal/ent/process.go @@ -0,0 +1,135 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "realm.pub/tavern/internal/ent/process" +) + +// Process is the model entity for the Process schema. +type Process struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // ID of the process. + Pid uint64 `json:"pid,omitempty"` + // The name of the process. + Name string `json:"name,omitempty"` + // The user the process is running as. + Principal string `json:"principal,omitempty"` + task_reported_processes *int + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Process) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case process.FieldID, process.FieldPid: + values[i] = new(sql.NullInt64) + case process.FieldName, process.FieldPrincipal: + values[i] = new(sql.NullString) + case process.ForeignKeys[0]: // task_reported_processes + values[i] = new(sql.NullInt64) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Process fields. +func (pr *Process) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case process.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + pr.ID = int(value.Int64) + case process.FieldPid: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field pid", values[i]) + } else if value.Valid { + pr.Pid = uint64(value.Int64) + } + case process.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + pr.Name = value.String + } + case process.FieldPrincipal: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field principal", values[i]) + } else if value.Valid { + pr.Principal = value.String + } + case process.ForeignKeys[0]: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field task_reported_processes", value) + } else if value.Valid { + pr.task_reported_processes = new(int) + *pr.task_reported_processes = int(value.Int64) + } + default: + pr.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the Process. +// This includes values selected through modifiers, order, etc. +func (pr *Process) Value(name string) (ent.Value, error) { + return pr.selectValues.Get(name) +} + +// Update returns a builder for updating this Process. +// Note that you need to call Process.Unwrap() before calling this method if this Process +// was returned from a transaction, and the transaction was committed or rolled back. +func (pr *Process) Update() *ProcessUpdateOne { + return NewProcessClient(pr.config).UpdateOne(pr) +} + +// Unwrap unwraps the Process entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (pr *Process) Unwrap() *Process { + _tx, ok := pr.config.driver.(*txDriver) + if !ok { + panic("ent: Process is not a transactional entity") + } + pr.config.driver = _tx.drv + return pr +} + +// String implements the fmt.Stringer. +func (pr *Process) String() string { + var builder strings.Builder + builder.WriteString("Process(") + builder.WriteString(fmt.Sprintf("id=%v, ", pr.ID)) + builder.WriteString("pid=") + builder.WriteString(fmt.Sprintf("%v", pr.Pid)) + builder.WriteString(", ") + builder.WriteString("name=") + builder.WriteString(pr.Name) + builder.WriteString(", ") + builder.WriteString("principal=") + builder.WriteString(pr.Principal) + builder.WriteByte(')') + return builder.String() +} + +// Processes is a parsable slice of Process. +type Processes []*Process diff --git a/tavern/internal/ent/process/process.go b/tavern/internal/ent/process/process.go new file mode 100644 index 000000000..ce6747efe --- /dev/null +++ b/tavern/internal/ent/process/process.go @@ -0,0 +1,79 @@ +// Code generated by ent, DO NOT EDIT. + +package process + +import ( + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the process type in the database. + Label = "process" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldPid holds the string denoting the pid field in the database. + FieldPid = "pid" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldPrincipal holds the string denoting the principal field in the database. + FieldPrincipal = "principal" + // Table holds the table name of the process in the database. + Table = "processes" +) + +// Columns holds all SQL columns for process fields. +var Columns = []string{ + FieldID, + FieldPid, + FieldName, + FieldPrincipal, +} + +// ForeignKeys holds the SQL foreign-keys that are owned by the "processes" +// table and are not defined as standalone fields in the schema. +var ForeignKeys = []string{ + "task_reported_processes", +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + for i := range ForeignKeys { + if column == ForeignKeys[i] { + return true + } + } + return false +} + +var ( + // PrincipalValidator is a validator for the "principal" field. It is called by the builders before save. + PrincipalValidator func(string) error +) + +// OrderOption defines the ordering options for the Process queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByPid orders the results by the pid field. +func ByPid(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPid, opts...).ToFunc() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByPrincipal orders the results by the principal field. +func ByPrincipal(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPrincipal, opts...).ToFunc() +} diff --git a/tavern/internal/ent/process/where.go b/tavern/internal/ent/process/where.go new file mode 100644 index 000000000..e6a3208f5 --- /dev/null +++ b/tavern/internal/ent/process/where.go @@ -0,0 +1,253 @@ +// Code generated by ent, DO NOT EDIT. + +package process + +import ( + "entgo.io/ent/dialect/sql" + "realm.pub/tavern/internal/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Process { + return predicate.Process(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Process { + return predicate.Process(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Process { + return predicate.Process(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Process { + return predicate.Process(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Process { + return predicate.Process(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Process { + return predicate.Process(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Process { + return predicate.Process(sql.FieldLTE(FieldID, id)) +} + +// Pid applies equality check predicate on the "pid" field. It's identical to PidEQ. +func Pid(v uint64) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldPid, v)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldName, v)) +} + +// Principal applies equality check predicate on the "principal" field. It's identical to PrincipalEQ. +func Principal(v string) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldPrincipal, v)) +} + +// PidEQ applies the EQ predicate on the "pid" field. +func PidEQ(v uint64) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldPid, v)) +} + +// PidNEQ applies the NEQ predicate on the "pid" field. +func PidNEQ(v uint64) predicate.Process { + return predicate.Process(sql.FieldNEQ(FieldPid, v)) +} + +// PidIn applies the In predicate on the "pid" field. +func PidIn(vs ...uint64) predicate.Process { + return predicate.Process(sql.FieldIn(FieldPid, vs...)) +} + +// PidNotIn applies the NotIn predicate on the "pid" field. +func PidNotIn(vs ...uint64) predicate.Process { + return predicate.Process(sql.FieldNotIn(FieldPid, vs...)) +} + +// PidGT applies the GT predicate on the "pid" field. +func PidGT(v uint64) predicate.Process { + return predicate.Process(sql.FieldGT(FieldPid, v)) +} + +// PidGTE applies the GTE predicate on the "pid" field. +func PidGTE(v uint64) predicate.Process { + return predicate.Process(sql.FieldGTE(FieldPid, v)) +} + +// PidLT applies the LT predicate on the "pid" field. +func PidLT(v uint64) predicate.Process { + return predicate.Process(sql.FieldLT(FieldPid, v)) +} + +// PidLTE applies the LTE predicate on the "pid" field. +func PidLTE(v uint64) predicate.Process { + return predicate.Process(sql.FieldLTE(FieldPid, v)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.Process { + return predicate.Process(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.Process { + return predicate.Process(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.Process { + return predicate.Process(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.Process { + return predicate.Process(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.Process { + return predicate.Process(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.Process { + return predicate.Process(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.Process { + return predicate.Process(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.Process { + return predicate.Process(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.Process { + return predicate.Process(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.Process { + return predicate.Process(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.Process { + return predicate.Process(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.Process { + return predicate.Process(sql.FieldContainsFold(FieldName, v)) +} + +// PrincipalEQ applies the EQ predicate on the "principal" field. +func PrincipalEQ(v string) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldPrincipal, v)) +} + +// PrincipalNEQ applies the NEQ predicate on the "principal" field. +func PrincipalNEQ(v string) predicate.Process { + return predicate.Process(sql.FieldNEQ(FieldPrincipal, v)) +} + +// PrincipalIn applies the In predicate on the "principal" field. +func PrincipalIn(vs ...string) predicate.Process { + return predicate.Process(sql.FieldIn(FieldPrincipal, vs...)) +} + +// PrincipalNotIn applies the NotIn predicate on the "principal" field. +func PrincipalNotIn(vs ...string) predicate.Process { + return predicate.Process(sql.FieldNotIn(FieldPrincipal, vs...)) +} + +// PrincipalGT applies the GT predicate on the "principal" field. +func PrincipalGT(v string) predicate.Process { + return predicate.Process(sql.FieldGT(FieldPrincipal, v)) +} + +// PrincipalGTE applies the GTE predicate on the "principal" field. +func PrincipalGTE(v string) predicate.Process { + return predicate.Process(sql.FieldGTE(FieldPrincipal, v)) +} + +// PrincipalLT applies the LT predicate on the "principal" field. +func PrincipalLT(v string) predicate.Process { + return predicate.Process(sql.FieldLT(FieldPrincipal, v)) +} + +// PrincipalLTE applies the LTE predicate on the "principal" field. +func PrincipalLTE(v string) predicate.Process { + return predicate.Process(sql.FieldLTE(FieldPrincipal, v)) +} + +// PrincipalContains applies the Contains predicate on the "principal" field. +func PrincipalContains(v string) predicate.Process { + return predicate.Process(sql.FieldContains(FieldPrincipal, v)) +} + +// PrincipalHasPrefix applies the HasPrefix predicate on the "principal" field. +func PrincipalHasPrefix(v string) predicate.Process { + return predicate.Process(sql.FieldHasPrefix(FieldPrincipal, v)) +} + +// PrincipalHasSuffix applies the HasSuffix predicate on the "principal" field. +func PrincipalHasSuffix(v string) predicate.Process { + return predicate.Process(sql.FieldHasSuffix(FieldPrincipal, v)) +} + +// PrincipalEqualFold applies the EqualFold predicate on the "principal" field. +func PrincipalEqualFold(v string) predicate.Process { + return predicate.Process(sql.FieldEqualFold(FieldPrincipal, v)) +} + +// PrincipalContainsFold applies the ContainsFold predicate on the "principal" field. +func PrincipalContainsFold(v string) predicate.Process { + return predicate.Process(sql.FieldContainsFold(FieldPrincipal, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Process) predicate.Process { + return predicate.Process(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Process) predicate.Process { + return predicate.Process(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Process) predicate.Process { + return predicate.Process(sql.NotPredicates(p)) +} diff --git a/tavern/internal/ent/process_create.go b/tavern/internal/ent/process_create.go new file mode 100644 index 000000000..64db05078 --- /dev/null +++ b/tavern/internal/ent/process_create.go @@ -0,0 +1,585 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/process" +) + +// ProcessCreate is the builder for creating a Process entity. +type ProcessCreate struct { + config + mutation *ProcessMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetPid sets the "pid" field. +func (pc *ProcessCreate) SetPid(u uint64) *ProcessCreate { + pc.mutation.SetPid(u) + return pc +} + +// SetName sets the "name" field. +func (pc *ProcessCreate) SetName(s string) *ProcessCreate { + pc.mutation.SetName(s) + return pc +} + +// SetPrincipal sets the "principal" field. +func (pc *ProcessCreate) SetPrincipal(s string) *ProcessCreate { + pc.mutation.SetPrincipal(s) + return pc +} + +// Mutation returns the ProcessMutation object of the builder. +func (pc *ProcessCreate) Mutation() *ProcessMutation { + return pc.mutation +} + +// Save creates the Process in the database. +func (pc *ProcessCreate) Save(ctx context.Context) (*Process, error) { + return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (pc *ProcessCreate) SaveX(ctx context.Context) *Process { + v, err := pc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pc *ProcessCreate) Exec(ctx context.Context) error { + _, err := pc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pc *ProcessCreate) ExecX(ctx context.Context) { + if err := pc.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (pc *ProcessCreate) check() error { + if _, ok := pc.mutation.Pid(); !ok { + return &ValidationError{Name: "pid", err: errors.New(`ent: missing required field "Process.pid"`)} + } + if _, ok := pc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Process.name"`)} + } + if _, ok := pc.mutation.Principal(); !ok { + return &ValidationError{Name: "principal", err: errors.New(`ent: missing required field "Process.principal"`)} + } + if v, ok := pc.mutation.Principal(); ok { + if err := process.PrincipalValidator(v); err != nil { + return &ValidationError{Name: "principal", err: fmt.Errorf(`ent: validator failed for field "Process.principal": %w`, err)} + } + } + return nil +} + +func (pc *ProcessCreate) sqlSave(ctx context.Context) (*Process, error) { + if err := pc.check(); err != nil { + return nil, err + } + _node, _spec := pc.createSpec() + if err := sqlgraph.CreateNode(ctx, pc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + pc.mutation.id = &_node.ID + pc.mutation.done = true + return _node, nil +} + +func (pc *ProcessCreate) createSpec() (*Process, *sqlgraph.CreateSpec) { + var ( + _node = &Process{config: pc.config} + _spec = sqlgraph.NewCreateSpec(process.Table, sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt)) + ) + _spec.OnConflict = pc.conflict + if value, ok := pc.mutation.Pid(); ok { + _spec.SetField(process.FieldPid, field.TypeUint64, value) + _node.Pid = value + } + if value, ok := pc.mutation.Name(); ok { + _spec.SetField(process.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := pc.mutation.Principal(); ok { + _spec.SetField(process.FieldPrincipal, field.TypeString, value) + _node.Principal = value + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.Process.Create(). +// SetPid(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.ProcessUpsert) { +// SetPid(v+v). +// }). +// Exec(ctx) +func (pc *ProcessCreate) OnConflict(opts ...sql.ConflictOption) *ProcessUpsertOne { + pc.conflict = opts + return &ProcessUpsertOne{ + create: pc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.Process.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (pc *ProcessCreate) OnConflictColumns(columns ...string) *ProcessUpsertOne { + pc.conflict = append(pc.conflict, sql.ConflictColumns(columns...)) + return &ProcessUpsertOne{ + create: pc, + } +} + +type ( + // ProcessUpsertOne is the builder for "upsert"-ing + // one Process node. + ProcessUpsertOne struct { + create *ProcessCreate + } + + // ProcessUpsert is the "OnConflict" setter. + ProcessUpsert struct { + *sql.UpdateSet + } +) + +// SetPid sets the "pid" field. +func (u *ProcessUpsert) SetPid(v uint64) *ProcessUpsert { + u.Set(process.FieldPid, v) + return u +} + +// UpdatePid sets the "pid" field to the value that was provided on create. +func (u *ProcessUpsert) UpdatePid() *ProcessUpsert { + u.SetExcluded(process.FieldPid) + return u +} + +// AddPid adds v to the "pid" field. +func (u *ProcessUpsert) AddPid(v uint64) *ProcessUpsert { + u.Add(process.FieldPid, v) + return u +} + +// SetName sets the "name" field. +func (u *ProcessUpsert) SetName(v string) *ProcessUpsert { + u.Set(process.FieldName, v) + return u +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ProcessUpsert) UpdateName() *ProcessUpsert { + u.SetExcluded(process.FieldName) + return u +} + +// SetPrincipal sets the "principal" field. +func (u *ProcessUpsert) SetPrincipal(v string) *ProcessUpsert { + u.Set(process.FieldPrincipal, v) + return u +} + +// UpdatePrincipal sets the "principal" field to the value that was provided on create. +func (u *ProcessUpsert) UpdatePrincipal() *ProcessUpsert { + u.SetExcluded(process.FieldPrincipal) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.Process.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *ProcessUpsertOne) UpdateNewValues() *ProcessUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.Process.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *ProcessUpsertOne) Ignore() *ProcessUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *ProcessUpsertOne) DoNothing() *ProcessUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the ProcessCreate.OnConflict +// documentation for more info. +func (u *ProcessUpsertOne) Update(set func(*ProcessUpsert)) *ProcessUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&ProcessUpsert{UpdateSet: update}) + })) + return u +} + +// SetPid sets the "pid" field. +func (u *ProcessUpsertOne) SetPid(v uint64) *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.SetPid(v) + }) +} + +// AddPid adds v to the "pid" field. +func (u *ProcessUpsertOne) AddPid(v uint64) *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.AddPid(v) + }) +} + +// UpdatePid sets the "pid" field to the value that was provided on create. +func (u *ProcessUpsertOne) UpdatePid() *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.UpdatePid() + }) +} + +// SetName sets the "name" field. +func (u *ProcessUpsertOne) SetName(v string) *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ProcessUpsertOne) UpdateName() *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.UpdateName() + }) +} + +// SetPrincipal sets the "principal" field. +func (u *ProcessUpsertOne) SetPrincipal(v string) *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.SetPrincipal(v) + }) +} + +// UpdatePrincipal sets the "principal" field to the value that was provided on create. +func (u *ProcessUpsertOne) UpdatePrincipal() *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.UpdatePrincipal() + }) +} + +// Exec executes the query. +func (u *ProcessUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for ProcessCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *ProcessUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *ProcessUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *ProcessUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// ProcessCreateBulk is the builder for creating many Process entities in bulk. +type ProcessCreateBulk struct { + config + err error + builders []*ProcessCreate + conflict []sql.ConflictOption +} + +// Save creates the Process entities in the database. +func (pcb *ProcessCreateBulk) Save(ctx context.Context) ([]*Process, error) { + if pcb.err != nil { + return nil, pcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(pcb.builders)) + nodes := make([]*Process, len(pcb.builders)) + mutators := make([]Mutator, len(pcb.builders)) + for i := range pcb.builders { + func(i int, root context.Context) { + builder := pcb.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*ProcessMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, pcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = pcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, pcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, pcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (pcb *ProcessCreateBulk) SaveX(ctx context.Context) []*Process { + v, err := pcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (pcb *ProcessCreateBulk) Exec(ctx context.Context) error { + _, err := pcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pcb *ProcessCreateBulk) ExecX(ctx context.Context) { + if err := pcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.Process.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.ProcessUpsert) { +// SetPid(v+v). +// }). +// Exec(ctx) +func (pcb *ProcessCreateBulk) OnConflict(opts ...sql.ConflictOption) *ProcessUpsertBulk { + pcb.conflict = opts + return &ProcessUpsertBulk{ + create: pcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.Process.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (pcb *ProcessCreateBulk) OnConflictColumns(columns ...string) *ProcessUpsertBulk { + pcb.conflict = append(pcb.conflict, sql.ConflictColumns(columns...)) + return &ProcessUpsertBulk{ + create: pcb, + } +} + +// ProcessUpsertBulk is the builder for "upsert"-ing +// a bulk of Process nodes. +type ProcessUpsertBulk struct { + create *ProcessCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.Process.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *ProcessUpsertBulk) UpdateNewValues() *ProcessUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.Process.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *ProcessUpsertBulk) Ignore() *ProcessUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *ProcessUpsertBulk) DoNothing() *ProcessUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the ProcessCreateBulk.OnConflict +// documentation for more info. +func (u *ProcessUpsertBulk) Update(set func(*ProcessUpsert)) *ProcessUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&ProcessUpsert{UpdateSet: update}) + })) + return u +} + +// SetPid sets the "pid" field. +func (u *ProcessUpsertBulk) SetPid(v uint64) *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.SetPid(v) + }) +} + +// AddPid adds v to the "pid" field. +func (u *ProcessUpsertBulk) AddPid(v uint64) *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.AddPid(v) + }) +} + +// UpdatePid sets the "pid" field to the value that was provided on create. +func (u *ProcessUpsertBulk) UpdatePid() *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.UpdatePid() + }) +} + +// SetName sets the "name" field. +func (u *ProcessUpsertBulk) SetName(v string) *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.SetName(v) + }) +} + +// UpdateName sets the "name" field to the value that was provided on create. +func (u *ProcessUpsertBulk) UpdateName() *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.UpdateName() + }) +} + +// SetPrincipal sets the "principal" field. +func (u *ProcessUpsertBulk) SetPrincipal(v string) *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.SetPrincipal(v) + }) +} + +// UpdatePrincipal sets the "principal" field to the value that was provided on create. +func (u *ProcessUpsertBulk) UpdatePrincipal() *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.UpdatePrincipal() + }) +} + +// Exec executes the query. +func (u *ProcessUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the ProcessCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for ProcessCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *ProcessUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/tavern/internal/ent/process_delete.go b/tavern/internal/ent/process_delete.go new file mode 100644 index 000000000..b2c7bd369 --- /dev/null +++ b/tavern/internal/ent/process_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" +) + +// ProcessDelete is the builder for deleting a Process entity. +type ProcessDelete struct { + config + hooks []Hook + mutation *ProcessMutation +} + +// Where appends a list predicates to the ProcessDelete builder. +func (pd *ProcessDelete) Where(ps ...predicate.Process) *ProcessDelete { + pd.mutation.Where(ps...) + return pd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (pd *ProcessDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, pd.sqlExec, pd.mutation, pd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (pd *ProcessDelete) ExecX(ctx context.Context) int { + n, err := pd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (pd *ProcessDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(process.Table, sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt)) + if ps := pd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, pd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + pd.mutation.done = true + return affected, err +} + +// ProcessDeleteOne is the builder for deleting a single Process entity. +type ProcessDeleteOne struct { + pd *ProcessDelete +} + +// Where appends a list predicates to the ProcessDelete builder. +func (pdo *ProcessDeleteOne) Where(ps ...predicate.Process) *ProcessDeleteOne { + pdo.pd.mutation.Where(ps...) + return pdo +} + +// Exec executes the deletion query. +func (pdo *ProcessDeleteOne) Exec(ctx context.Context) error { + n, err := pdo.pd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{process.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (pdo *ProcessDeleteOne) ExecX(ctx context.Context) { + if err := pdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/tavern/internal/ent/process_query.go b/tavern/internal/ent/process_query.go new file mode 100644 index 000000000..3d9580c03 --- /dev/null +++ b/tavern/internal/ent/process_query.go @@ -0,0 +1,544 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" +) + +// ProcessQuery is the builder for querying Process entities. +type ProcessQuery struct { + config + ctx *QueryContext + order []process.OrderOption + inters []Interceptor + predicates []predicate.Process + withFKs bool + modifiers []func(*sql.Selector) + loadTotal []func(context.Context, []*Process) error + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the ProcessQuery builder. +func (pq *ProcessQuery) Where(ps ...predicate.Process) *ProcessQuery { + pq.predicates = append(pq.predicates, ps...) + return pq +} + +// Limit the number of records to be returned by this query. +func (pq *ProcessQuery) Limit(limit int) *ProcessQuery { + pq.ctx.Limit = &limit + return pq +} + +// Offset to start from. +func (pq *ProcessQuery) Offset(offset int) *ProcessQuery { + pq.ctx.Offset = &offset + return pq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (pq *ProcessQuery) Unique(unique bool) *ProcessQuery { + pq.ctx.Unique = &unique + return pq +} + +// Order specifies how the records should be ordered. +func (pq *ProcessQuery) Order(o ...process.OrderOption) *ProcessQuery { + pq.order = append(pq.order, o...) + return pq +} + +// First returns the first Process entity from the query. +// Returns a *NotFoundError when no Process was found. +func (pq *ProcessQuery) First(ctx context.Context) (*Process, error) { + nodes, err := pq.Limit(1).All(setContextOp(ctx, pq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{process.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (pq *ProcessQuery) FirstX(ctx context.Context) *Process { + node, err := pq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Process ID from the query. +// Returns a *NotFoundError when no Process ID was found. +func (pq *ProcessQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = pq.Limit(1).IDs(setContextOp(ctx, pq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{process.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (pq *ProcessQuery) FirstIDX(ctx context.Context) int { + id, err := pq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Process entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one Process entity is found. +// Returns a *NotFoundError when no Process entities are found. +func (pq *ProcessQuery) Only(ctx context.Context) (*Process, error) { + nodes, err := pq.Limit(2).All(setContextOp(ctx, pq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{process.Label} + default: + return nil, &NotSingularError{process.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (pq *ProcessQuery) OnlyX(ctx context.Context) *Process { + node, err := pq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Process ID in the query. +// Returns a *NotSingularError when more than one Process ID is found. +// Returns a *NotFoundError when no entities are found. +func (pq *ProcessQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = pq.Limit(2).IDs(setContextOp(ctx, pq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{process.Label} + default: + err = &NotSingularError{process.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (pq *ProcessQuery) OnlyIDX(ctx context.Context) int { + id, err := pq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Processes. +func (pq *ProcessQuery) All(ctx context.Context) ([]*Process, error) { + ctx = setContextOp(ctx, pq.ctx, "All") + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*Process, *ProcessQuery]() + return withInterceptors[[]*Process](ctx, pq, qr, pq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (pq *ProcessQuery) AllX(ctx context.Context) []*Process { + nodes, err := pq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Process IDs. +func (pq *ProcessQuery) IDs(ctx context.Context) (ids []int, err error) { + if pq.ctx.Unique == nil && pq.path != nil { + pq.Unique(true) + } + ctx = setContextOp(ctx, pq.ctx, "IDs") + if err = pq.Select(process.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (pq *ProcessQuery) IDsX(ctx context.Context) []int { + ids, err := pq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (pq *ProcessQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, pq.ctx, "Count") + if err := pq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, pq, querierCount[*ProcessQuery](), pq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (pq *ProcessQuery) CountX(ctx context.Context) int { + count, err := pq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (pq *ProcessQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, pq.ctx, "Exist") + switch _, err := pq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (pq *ProcessQuery) ExistX(ctx context.Context) bool { + exist, err := pq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the ProcessQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (pq *ProcessQuery) Clone() *ProcessQuery { + if pq == nil { + return nil + } + return &ProcessQuery{ + config: pq.config, + ctx: pq.ctx.Clone(), + order: append([]process.OrderOption{}, pq.order...), + inters: append([]Interceptor{}, pq.inters...), + predicates: append([]predicate.Process{}, pq.predicates...), + // clone intermediate query. + sql: pq.sql.Clone(), + path: pq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Pid uint64 `json:"pid,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Process.Query(). +// GroupBy(process.FieldPid). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (pq *ProcessQuery) GroupBy(field string, fields ...string) *ProcessGroupBy { + pq.ctx.Fields = append([]string{field}, fields...) + grbuild := &ProcessGroupBy{build: pq} + grbuild.flds = &pq.ctx.Fields + grbuild.label = process.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Pid uint64 `json:"pid,omitempty"` +// } +// +// client.Process.Query(). +// Select(process.FieldPid). +// Scan(ctx, &v) +func (pq *ProcessQuery) Select(fields ...string) *ProcessSelect { + pq.ctx.Fields = append(pq.ctx.Fields, fields...) + sbuild := &ProcessSelect{ProcessQuery: pq} + sbuild.label = process.Label + sbuild.flds, sbuild.scan = &pq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a ProcessSelect configured with the given aggregations. +func (pq *ProcessQuery) Aggregate(fns ...AggregateFunc) *ProcessSelect { + return pq.Select().Aggregate(fns...) +} + +func (pq *ProcessQuery) prepareQuery(ctx context.Context) error { + for _, inter := range pq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, pq); err != nil { + return err + } + } + } + for _, f := range pq.ctx.Fields { + if !process.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if pq.path != nil { + prev, err := pq.path(ctx) + if err != nil { + return err + } + pq.sql = prev + } + return nil +} + +func (pq *ProcessQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Process, error) { + var ( + nodes = []*Process{} + withFKs = pq.withFKs + _spec = pq.querySpec() + ) + if withFKs { + _spec.Node.Columns = append(_spec.Node.Columns, process.ForeignKeys...) + } + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*Process).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &Process{config: pq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + if len(pq.modifiers) > 0 { + _spec.Modifiers = pq.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, pq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + for i := range pq.loadTotal { + if err := pq.loadTotal[i](ctx, nodes); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (pq *ProcessQuery) sqlCount(ctx context.Context) (int, error) { + _spec := pq.querySpec() + if len(pq.modifiers) > 0 { + _spec.Modifiers = pq.modifiers + } + _spec.Node.Columns = pq.ctx.Fields + if len(pq.ctx.Fields) > 0 { + _spec.Unique = pq.ctx.Unique != nil && *pq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, pq.driver, _spec) +} + +func (pq *ProcessQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(process.Table, process.Columns, sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt)) + _spec.From = pq.sql + if unique := pq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if pq.path != nil { + _spec.Unique = true + } + if fields := pq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, process.FieldID) + for i := range fields { + if fields[i] != process.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := pq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := pq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := pq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := pq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (pq *ProcessQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(pq.driver.Dialect()) + t1 := builder.Table(process.Table) + columns := pq.ctx.Fields + if len(columns) == 0 { + columns = process.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if pq.sql != nil { + selector = pq.sql + selector.Select(selector.Columns(columns...)...) + } + if pq.ctx.Unique != nil && *pq.ctx.Unique { + selector.Distinct() + } + for _, p := range pq.predicates { + p(selector) + } + for _, p := range pq.order { + p(selector) + } + if offset := pq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := pq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// ProcessGroupBy is the group-by builder for Process entities. +type ProcessGroupBy struct { + selector + build *ProcessQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (pgb *ProcessGroupBy) Aggregate(fns ...AggregateFunc) *ProcessGroupBy { + pgb.fns = append(pgb.fns, fns...) + return pgb +} + +// Scan applies the selector query and scans the result into the given value. +func (pgb *ProcessGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, pgb.build.ctx, "GroupBy") + if err := pgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ProcessQuery, *ProcessGroupBy](ctx, pgb.build, pgb, pgb.build.inters, v) +} + +func (pgb *ProcessGroupBy) sqlScan(ctx context.Context, root *ProcessQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(pgb.fns)) + for _, fn := range pgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*pgb.flds)+len(pgb.fns)) + for _, f := range *pgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*pgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := pgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// ProcessSelect is the builder for selecting fields of Process entities. +type ProcessSelect struct { + *ProcessQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ps *ProcessSelect) Aggregate(fns ...AggregateFunc) *ProcessSelect { + ps.fns = append(ps.fns, fns...) + return ps +} + +// Scan applies the selector query and scans the result into the given value. +func (ps *ProcessSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ps.ctx, "Select") + if err := ps.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*ProcessQuery, *ProcessSelect](ctx, ps.ProcessQuery, ps, ps.inters, v) +} + +func (ps *ProcessSelect) sqlScan(ctx context.Context, root *ProcessQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ps.fns)) + for _, fn := range ps.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ps.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ps.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/tavern/internal/ent/process_update.go b/tavern/internal/ent/process_update.go new file mode 100644 index 000000000..146a8b6d4 --- /dev/null +++ b/tavern/internal/ent/process_update.go @@ -0,0 +1,275 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" +) + +// ProcessUpdate is the builder for updating Process entities. +type ProcessUpdate struct { + config + hooks []Hook + mutation *ProcessMutation +} + +// Where appends a list predicates to the ProcessUpdate builder. +func (pu *ProcessUpdate) Where(ps ...predicate.Process) *ProcessUpdate { + pu.mutation.Where(ps...) + return pu +} + +// SetPid sets the "pid" field. +func (pu *ProcessUpdate) SetPid(u uint64) *ProcessUpdate { + pu.mutation.ResetPid() + pu.mutation.SetPid(u) + return pu +} + +// AddPid adds u to the "pid" field. +func (pu *ProcessUpdate) AddPid(u int64) *ProcessUpdate { + pu.mutation.AddPid(u) + return pu +} + +// SetName sets the "name" field. +func (pu *ProcessUpdate) SetName(s string) *ProcessUpdate { + pu.mutation.SetName(s) + return pu +} + +// SetPrincipal sets the "principal" field. +func (pu *ProcessUpdate) SetPrincipal(s string) *ProcessUpdate { + pu.mutation.SetPrincipal(s) + return pu +} + +// Mutation returns the ProcessMutation object of the builder. +func (pu *ProcessUpdate) Mutation() *ProcessMutation { + return pu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (pu *ProcessUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, pu.sqlSave, pu.mutation, pu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (pu *ProcessUpdate) SaveX(ctx context.Context) int { + affected, err := pu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (pu *ProcessUpdate) Exec(ctx context.Context) error { + _, err := pu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (pu *ProcessUpdate) ExecX(ctx context.Context) { + if err := pu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (pu *ProcessUpdate) check() error { + if v, ok := pu.mutation.Principal(); ok { + if err := process.PrincipalValidator(v); err != nil { + return &ValidationError{Name: "principal", err: fmt.Errorf(`ent: validator failed for field "Process.principal": %w`, err)} + } + } + return nil +} + +func (pu *ProcessUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := pu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(process.Table, process.Columns, sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt)) + if ps := pu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := pu.mutation.Pid(); ok { + _spec.SetField(process.FieldPid, field.TypeUint64, value) + } + if value, ok := pu.mutation.AddedPid(); ok { + _spec.AddField(process.FieldPid, field.TypeUint64, value) + } + if value, ok := pu.mutation.Name(); ok { + _spec.SetField(process.FieldName, field.TypeString, value) + } + if value, ok := pu.mutation.Principal(); ok { + _spec.SetField(process.FieldPrincipal, field.TypeString, value) + } + if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{process.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + pu.mutation.done = true + return n, nil +} + +// ProcessUpdateOne is the builder for updating a single Process entity. +type ProcessUpdateOne struct { + config + fields []string + hooks []Hook + mutation *ProcessMutation +} + +// SetPid sets the "pid" field. +func (puo *ProcessUpdateOne) SetPid(u uint64) *ProcessUpdateOne { + puo.mutation.ResetPid() + puo.mutation.SetPid(u) + return puo +} + +// AddPid adds u to the "pid" field. +func (puo *ProcessUpdateOne) AddPid(u int64) *ProcessUpdateOne { + puo.mutation.AddPid(u) + return puo +} + +// SetName sets the "name" field. +func (puo *ProcessUpdateOne) SetName(s string) *ProcessUpdateOne { + puo.mutation.SetName(s) + return puo +} + +// SetPrincipal sets the "principal" field. +func (puo *ProcessUpdateOne) SetPrincipal(s string) *ProcessUpdateOne { + puo.mutation.SetPrincipal(s) + return puo +} + +// Mutation returns the ProcessMutation object of the builder. +func (puo *ProcessUpdateOne) Mutation() *ProcessMutation { + return puo.mutation +} + +// Where appends a list predicates to the ProcessUpdate builder. +func (puo *ProcessUpdateOne) Where(ps ...predicate.Process) *ProcessUpdateOne { + puo.mutation.Where(ps...) + return puo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (puo *ProcessUpdateOne) Select(field string, fields ...string) *ProcessUpdateOne { + puo.fields = append([]string{field}, fields...) + return puo +} + +// Save executes the query and returns the updated Process entity. +func (puo *ProcessUpdateOne) Save(ctx context.Context) (*Process, error) { + return withHooks(ctx, puo.sqlSave, puo.mutation, puo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (puo *ProcessUpdateOne) SaveX(ctx context.Context) *Process { + node, err := puo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (puo *ProcessUpdateOne) Exec(ctx context.Context) error { + _, err := puo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (puo *ProcessUpdateOne) ExecX(ctx context.Context) { + if err := puo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (puo *ProcessUpdateOne) check() error { + if v, ok := puo.mutation.Principal(); ok { + if err := process.PrincipalValidator(v); err != nil { + return &ValidationError{Name: "principal", err: fmt.Errorf(`ent: validator failed for field "Process.principal": %w`, err)} + } + } + return nil +} + +func (puo *ProcessUpdateOne) sqlSave(ctx context.Context) (_node *Process, err error) { + if err := puo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(process.Table, process.Columns, sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt)) + id, ok := puo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Process.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := puo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, process.FieldID) + for _, f := range fields { + if !process.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != process.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := puo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := puo.mutation.Pid(); ok { + _spec.SetField(process.FieldPid, field.TypeUint64, value) + } + if value, ok := puo.mutation.AddedPid(); ok { + _spec.AddField(process.FieldPid, field.TypeUint64, value) + } + if value, ok := puo.mutation.Name(); ok { + _spec.SetField(process.FieldName, field.TypeString, value) + } + if value, ok := puo.mutation.Principal(); ok { + _spec.SetField(process.FieldPrincipal, field.TypeString, value) + } + _node = &Process{config: puo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, puo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{process.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + puo.mutation.done = true + return _node, nil +} diff --git a/tavern/internal/ent/runtime/runtime.go b/tavern/internal/ent/runtime/runtime.go index 476fa0d24..6c1faadb3 100644 --- a/tavern/internal/ent/runtime/runtime.go +++ b/tavern/internal/ent/runtime/runtime.go @@ -8,6 +8,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/file" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/schema" "realm.pub/tavern/internal/ent/tag" @@ -83,6 +84,12 @@ func init() { hostDescName := hostFields[1].Descriptor() // host.NameValidator is a validator for the "name" field. It is called by the builders before save. host.NameValidator = hostDescName.Validators[0].(func(string) error) + processFields := schema.Process{}.Fields() + _ = processFields + // processDescPrincipal is the schema descriptor for principal field. + processDescPrincipal := processFields[2].Descriptor() + // process.PrincipalValidator is a validator for the "principal" field. It is called by the builders before save. + process.PrincipalValidator = processDescPrincipal.Validators[0].(func(string) error) questMixin := schema.Quest{}.Mixin() questMixinFields0 := questMixin[0].Fields() _ = questMixinFields0 diff --git a/tavern/internal/ent/schema/process.go b/tavern/internal/ent/schema/process.go new file mode 100644 index 000000000..c05cf7774 --- /dev/null +++ b/tavern/internal/ent/schema/process.go @@ -0,0 +1,54 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema" + "entgo.io/ent/schema/field" +) + +// Process holds the schema definition for the Process entity. +type Process struct { + ent.Schema +} + +// Fields of the ent. +func (Process) Fields() []ent.Field { + return []ent.Field{ + field.Uint64("pid"). + Comment("ID of the process."), + field.String("name"). + Comment("The name of the process."), + field.String("principal"). + NotEmpty(). + Comment("The user the process is running as."), + } +} + +// Edges of the ent. +func (Process) Edges() []ent.Edge { + return []ent.Edge{ + // edge.To("host", Host.Type). + // Required(). + // Unique(). + // Comment("Host the process was reported on."), + // edge.From("task", Task.Type). + // Required(). + // Unique(). + // Ref("reported_processes"). + // Comment("Task that reported this process."), + } +} + +// Annotations describes additional information for the ent. +func (Process) Annotations() []schema.Annotation { + return []schema.Annotation{ + // entgql.Skip(entgql.SkipMutationCreateInput, entgql.SkipMutationUpdateInput), + } +} + +// Mixin defines common shared properties for the ent. +func (Process) Mixin() []ent.Mixin { + return []ent.Mixin{ + // MixinHistory{}, // created_at, last_modified_at + } +} diff --git a/tavern/internal/ent/schema/task.go b/tavern/internal/ent/schema/task.go index 7dedb5f1a..f39a93b00 100644 --- a/tavern/internal/ent/schema/task.go +++ b/tavern/internal/ent/schema/task.go @@ -64,6 +64,8 @@ func (Task) Edges() []ent.Edge { edge.To("beacon", Beacon.Type). Required(). Unique(), + edge.To("reported_processes", Process.Type). + Comment("Processes that have been reported by this task."), } } diff --git a/tavern/internal/ent/task.go b/tavern/internal/ent/task.go index b00f701bb..4c2c5d94b 100644 --- a/tavern/internal/ent/task.go +++ b/tavern/internal/ent/task.go @@ -49,11 +49,15 @@ type TaskEdges struct { Quest *Quest `json:"quest,omitempty"` // Beacon holds the value of the beacon edge. Beacon *Beacon `json:"beacon,omitempty"` + // Processes that have been reported by this task. + ReportedProcesses []*Process `json:"reported_processes,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [3]bool // totalCount holds the count of the edges above. - totalCount [2]map[string]int + totalCount [3]map[string]int + + namedReportedProcesses map[string][]*Process } // QuestOrErr returns the Quest value or an error if the edge @@ -82,6 +86,15 @@ func (e TaskEdges) BeaconOrErr() (*Beacon, error) { return nil, &NotLoadedError{edge: "beacon"} } +// ReportedProcessesOrErr returns the ReportedProcesses value or an error if the edge +// was not loaded in eager-loading. +func (e TaskEdges) ReportedProcessesOrErr() ([]*Process, error) { + if e.loadedTypes[2] { + return e.ReportedProcesses, nil + } + return nil, &NotLoadedError{edge: "reported_processes"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Task) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) @@ -203,6 +216,11 @@ func (t *Task) QueryBeacon() *BeaconQuery { return NewTaskClient(t.config).QueryBeacon(t) } +// QueryReportedProcesses queries the "reported_processes" edge of the Task entity. +func (t *Task) QueryReportedProcesses() *ProcessQuery { + return NewTaskClient(t.config).QueryReportedProcesses(t) +} + // Update returns a builder for updating this Task. // Note that you need to call Task.Unwrap() before calling this method if this Task // was returned from a transaction, and the transaction was committed or rolled back. @@ -253,5 +271,29 @@ func (t *Task) String() string { return builder.String() } +// NamedReportedProcesses returns the ReportedProcesses named value or an error if the edge was not +// loaded in eager-loading with this name. +func (t *Task) NamedReportedProcesses(name string) ([]*Process, error) { + if t.Edges.namedReportedProcesses == nil { + return nil, &NotLoadedError{edge: name} + } + nodes, ok := t.Edges.namedReportedProcesses[name] + if !ok { + return nil, &NotLoadedError{edge: name} + } + return nodes, nil +} + +func (t *Task) appendNamedReportedProcesses(name string, edges ...*Process) { + if t.Edges.namedReportedProcesses == nil { + t.Edges.namedReportedProcesses = make(map[string][]*Process) + } + if len(edges) == 0 { + t.Edges.namedReportedProcesses[name] = []*Process{} + } else { + t.Edges.namedReportedProcesses[name] = append(t.Edges.namedReportedProcesses[name], edges...) + } +} + // Tasks is a parsable slice of Task. type Tasks []*Task diff --git a/tavern/internal/ent/task/task.go b/tavern/internal/ent/task/task.go index b03cf5e6c..37bc1628d 100644 --- a/tavern/internal/ent/task/task.go +++ b/tavern/internal/ent/task/task.go @@ -35,6 +35,8 @@ const ( EdgeQuest = "quest" // EdgeBeacon holds the string denoting the beacon edge name in mutations. EdgeBeacon = "beacon" + // EdgeReportedProcesses holds the string denoting the reported_processes edge name in mutations. + EdgeReportedProcesses = "reported_processes" // Table holds the table name of the task in the database. Table = "tasks" // QuestTable is the table that holds the quest relation/edge. @@ -51,6 +53,13 @@ const ( BeaconInverseTable = "beacons" // BeaconColumn is the table column denoting the beacon relation/edge. BeaconColumn = "task_beacon" + // ReportedProcessesTable is the table that holds the reported_processes relation/edge. + ReportedProcessesTable = "processes" + // ReportedProcessesInverseTable is the table name for the Process entity. + // It exists in this package in order to avoid circular dependency with the "process" package. + ReportedProcessesInverseTable = "processes" + // ReportedProcessesColumn is the table column denoting the reported_processes relation/edge. + ReportedProcessesColumn = "task_reported_processes" ) // Columns holds all SQL columns for task fields. @@ -168,6 +177,20 @@ func ByBeaconField(field string, opts ...sql.OrderTermOption) OrderOption { sqlgraph.OrderByNeighborTerms(s, newBeaconStep(), sql.OrderByField(field, opts...)) } } + +// ByReportedProcessesCount orders the results by reported_processes count. +func ByReportedProcessesCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newReportedProcessesStep(), opts...) + } +} + +// ByReportedProcesses orders the results by reported_processes terms. +func ByReportedProcesses(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newReportedProcessesStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} func newQuestStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -182,3 +205,10 @@ func newBeaconStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.M2O, false, BeaconTable, BeaconColumn), ) } +func newReportedProcessesStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ReportedProcessesInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ReportedProcessesTable, ReportedProcessesColumn), + ) +} diff --git a/tavern/internal/ent/task/where.go b/tavern/internal/ent/task/where.go index fa4aff0f3..ccdf8b502 100644 --- a/tavern/internal/ent/task/where.go +++ b/tavern/internal/ent/task/where.go @@ -561,6 +561,29 @@ func HasBeaconWith(preds ...predicate.Beacon) predicate.Task { }) } +// HasReportedProcesses applies the HasEdge predicate on the "reported_processes" edge. +func HasReportedProcesses() predicate.Task { + return predicate.Task(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ReportedProcessesTable, ReportedProcessesColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasReportedProcessesWith applies the HasEdge predicate on the "reported_processes" edge with a given conditions (other predicates). +func HasReportedProcessesWith(preds ...predicate.Process) predicate.Task { + return predicate.Task(func(s *sql.Selector) { + step := newReportedProcessesStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Task) predicate.Task { return predicate.Task(sql.AndPredicates(predicates...)) diff --git a/tavern/internal/ent/task_create.go b/tavern/internal/ent/task_create.go index 1b7c7d816..0dc601297 100644 --- a/tavern/internal/ent/task_create.go +++ b/tavern/internal/ent/task_create.go @@ -12,6 +12,7 @@ import ( "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" "realm.pub/tavern/internal/ent/beacon" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/task" ) @@ -158,6 +159,21 @@ func (tc *TaskCreate) SetBeacon(b *Beacon) *TaskCreate { return tc.SetBeaconID(b.ID) } +// AddReportedProcessIDs adds the "reported_processes" edge to the Process entity by IDs. +func (tc *TaskCreate) AddReportedProcessIDs(ids ...int) *TaskCreate { + tc.mutation.AddReportedProcessIDs(ids...) + return tc +} + +// AddReportedProcesses adds the "reported_processes" edges to the Process entity. +func (tc *TaskCreate) AddReportedProcesses(p ...*Process) *TaskCreate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return tc.AddReportedProcessIDs(ids...) +} + // Mutation returns the TaskMutation object of the builder. func (tc *TaskCreate) Mutation() *TaskMutation { return tc.mutation @@ -331,6 +347,22 @@ func (tc *TaskCreate) createSpec() (*Task, *sqlgraph.CreateSpec) { _node.task_beacon = &nodes[0] _spec.Edges = append(_spec.Edges, edge) } + if nodes := tc.mutation.ReportedProcessesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/tavern/internal/ent/task_query.go b/tavern/internal/ent/task_query.go index e7a8cf367..581996829 100644 --- a/tavern/internal/ent/task_query.go +++ b/tavern/internal/ent/task_query.go @@ -4,6 +4,7 @@ package ent import ( "context" + "database/sql/driver" "fmt" "math" @@ -12,6 +13,7 @@ import ( "entgo.io/ent/schema/field" "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/task" ) @@ -19,15 +21,17 @@ import ( // TaskQuery is the builder for querying Task entities. type TaskQuery struct { config - ctx *QueryContext - order []task.OrderOption - inters []Interceptor - predicates []predicate.Task - withQuest *QuestQuery - withBeacon *BeaconQuery - withFKs bool - modifiers []func(*sql.Selector) - loadTotal []func(context.Context, []*Task) error + ctx *QueryContext + order []task.OrderOption + inters []Interceptor + predicates []predicate.Task + withQuest *QuestQuery + withBeacon *BeaconQuery + withReportedProcesses *ProcessQuery + withFKs bool + modifiers []func(*sql.Selector) + loadTotal []func(context.Context, []*Task) error + withNamedReportedProcesses map[string]*ProcessQuery // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -108,6 +112,28 @@ func (tq *TaskQuery) QueryBeacon() *BeaconQuery { return query } +// QueryReportedProcesses chains the current query on the "reported_processes" edge. +func (tq *TaskQuery) QueryReportedProcesses() *ProcessQuery { + query := (&ProcessClient{config: tq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := tq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(task.Table, task.FieldID, selector), + sqlgraph.To(process.Table, process.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, task.ReportedProcessesTable, task.ReportedProcessesColumn), + ) + fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Task entity from the query. // Returns a *NotFoundError when no Task was found. func (tq *TaskQuery) First(ctx context.Context) (*Task, error) { @@ -295,13 +321,14 @@ func (tq *TaskQuery) Clone() *TaskQuery { return nil } return &TaskQuery{ - config: tq.config, - ctx: tq.ctx.Clone(), - order: append([]task.OrderOption{}, tq.order...), - inters: append([]Interceptor{}, tq.inters...), - predicates: append([]predicate.Task{}, tq.predicates...), - withQuest: tq.withQuest.Clone(), - withBeacon: tq.withBeacon.Clone(), + config: tq.config, + ctx: tq.ctx.Clone(), + order: append([]task.OrderOption{}, tq.order...), + inters: append([]Interceptor{}, tq.inters...), + predicates: append([]predicate.Task{}, tq.predicates...), + withQuest: tq.withQuest.Clone(), + withBeacon: tq.withBeacon.Clone(), + withReportedProcesses: tq.withReportedProcesses.Clone(), // clone intermediate query. sql: tq.sql.Clone(), path: tq.path, @@ -330,6 +357,17 @@ func (tq *TaskQuery) WithBeacon(opts ...func(*BeaconQuery)) *TaskQuery { return tq } +// WithReportedProcesses tells the query-builder to eager-load the nodes that are connected to +// the "reported_processes" edge. The optional arguments are used to configure the query builder of the edge. +func (tq *TaskQuery) WithReportedProcesses(opts ...func(*ProcessQuery)) *TaskQuery { + query := (&ProcessClient{config: tq.config}).Query() + for _, opt := range opts { + opt(query) + } + tq.withReportedProcesses = query + return tq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -409,9 +447,10 @@ func (tq *TaskQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Task, e nodes = []*Task{} withFKs = tq.withFKs _spec = tq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [3]bool{ tq.withQuest != nil, tq.withBeacon != nil, + tq.withReportedProcesses != nil, } ) if tq.withQuest != nil || tq.withBeacon != nil { @@ -453,6 +492,20 @@ func (tq *TaskQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Task, e return nil, err } } + if query := tq.withReportedProcesses; query != nil { + if err := tq.loadReportedProcesses(ctx, query, nodes, + func(n *Task) { n.Edges.ReportedProcesses = []*Process{} }, + func(n *Task, e *Process) { n.Edges.ReportedProcesses = append(n.Edges.ReportedProcesses, e) }); err != nil { + return nil, err + } + } + for name, query := range tq.withNamedReportedProcesses { + if err := tq.loadReportedProcesses(ctx, query, nodes, + func(n *Task) { n.appendNamedReportedProcesses(name) }, + func(n *Task, e *Process) { n.appendNamedReportedProcesses(name, e) }); err != nil { + return nil, err + } + } for i := range tq.loadTotal { if err := tq.loadTotal[i](ctx, nodes); err != nil { return nil, err @@ -525,6 +578,37 @@ func (tq *TaskQuery) loadBeacon(ctx context.Context, query *BeaconQuery, nodes [ } return nil } +func (tq *TaskQuery) loadReportedProcesses(ctx context.Context, query *ProcessQuery, nodes []*Task, init func(*Task), assign func(*Task, *Process)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Task) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + query.withFKs = true + query.Where(predicate.Process(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(task.ReportedProcessesColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.task_reported_processes + if fk == nil { + return fmt.Errorf(`foreign-key "task_reported_processes" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "task_reported_processes" returned %v for node %v`, *fk, n.ID) + } + assign(node, n) + } + return nil +} func (tq *TaskQuery) sqlCount(ctx context.Context) (int, error) { _spec := tq.querySpec() @@ -610,6 +694,20 @@ func (tq *TaskQuery) sqlQuery(ctx context.Context) *sql.Selector { return selector } +// WithNamedReportedProcesses tells the query-builder to eager-load the nodes that are connected to the "reported_processes" +// edge with the given name. The optional arguments are used to configure the query builder of the edge. +func (tq *TaskQuery) WithNamedReportedProcesses(name string, opts ...func(*ProcessQuery)) *TaskQuery { + query := (&ProcessClient{config: tq.config}).Query() + for _, opt := range opts { + opt(query) + } + if tq.withNamedReportedProcesses == nil { + tq.withNamedReportedProcesses = make(map[string]*ProcessQuery) + } + tq.withNamedReportedProcesses[name] = query + return tq +} + // TaskGroupBy is the group-by builder for Task entities. type TaskGroupBy struct { selector diff --git a/tavern/internal/ent/task_update.go b/tavern/internal/ent/task_update.go index 7e3bd5ac7..716c39469 100644 --- a/tavern/internal/ent/task_update.go +++ b/tavern/internal/ent/task_update.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/schema/field" "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/quest" "realm.pub/tavern/internal/ent/task" ) @@ -179,6 +180,21 @@ func (tu *TaskUpdate) SetBeacon(b *Beacon) *TaskUpdate { return tu.SetBeaconID(b.ID) } +// AddReportedProcessIDs adds the "reported_processes" edge to the Process entity by IDs. +func (tu *TaskUpdate) AddReportedProcessIDs(ids ...int) *TaskUpdate { + tu.mutation.AddReportedProcessIDs(ids...) + return tu +} + +// AddReportedProcesses adds the "reported_processes" edges to the Process entity. +func (tu *TaskUpdate) AddReportedProcesses(p ...*Process) *TaskUpdate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return tu.AddReportedProcessIDs(ids...) +} + // Mutation returns the TaskMutation object of the builder. func (tu *TaskUpdate) Mutation() *TaskMutation { return tu.mutation @@ -196,6 +212,27 @@ func (tu *TaskUpdate) ClearBeacon() *TaskUpdate { return tu } +// ClearReportedProcesses clears all "reported_processes" edges to the Process entity. +func (tu *TaskUpdate) ClearReportedProcesses() *TaskUpdate { + tu.mutation.ClearReportedProcesses() + return tu +} + +// RemoveReportedProcessIDs removes the "reported_processes" edge to Process entities by IDs. +func (tu *TaskUpdate) RemoveReportedProcessIDs(ids ...int) *TaskUpdate { + tu.mutation.RemoveReportedProcessIDs(ids...) + return tu +} + +// RemoveReportedProcesses removes "reported_processes" edges to Process entities. +func (tu *TaskUpdate) RemoveReportedProcesses(p ...*Process) *TaskUpdate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return tu.RemoveReportedProcessIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (tu *TaskUpdate) Save(ctx context.Context) (int, error) { if err := tu.defaults(); err != nil { @@ -363,6 +400,51 @@ func (tu *TaskUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if tu.mutation.ReportedProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.RemovedReportedProcessesIDs(); len(nodes) > 0 && !tu.mutation.ReportedProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.ReportedProcessesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, tu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{task.Label} @@ -532,6 +614,21 @@ func (tuo *TaskUpdateOne) SetBeacon(b *Beacon) *TaskUpdateOne { return tuo.SetBeaconID(b.ID) } +// AddReportedProcessIDs adds the "reported_processes" edge to the Process entity by IDs. +func (tuo *TaskUpdateOne) AddReportedProcessIDs(ids ...int) *TaskUpdateOne { + tuo.mutation.AddReportedProcessIDs(ids...) + return tuo +} + +// AddReportedProcesses adds the "reported_processes" edges to the Process entity. +func (tuo *TaskUpdateOne) AddReportedProcesses(p ...*Process) *TaskUpdateOne { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return tuo.AddReportedProcessIDs(ids...) +} + // Mutation returns the TaskMutation object of the builder. func (tuo *TaskUpdateOne) Mutation() *TaskMutation { return tuo.mutation @@ -549,6 +646,27 @@ func (tuo *TaskUpdateOne) ClearBeacon() *TaskUpdateOne { return tuo } +// ClearReportedProcesses clears all "reported_processes" edges to the Process entity. +func (tuo *TaskUpdateOne) ClearReportedProcesses() *TaskUpdateOne { + tuo.mutation.ClearReportedProcesses() + return tuo +} + +// RemoveReportedProcessIDs removes the "reported_processes" edge to Process entities by IDs. +func (tuo *TaskUpdateOne) RemoveReportedProcessIDs(ids ...int) *TaskUpdateOne { + tuo.mutation.RemoveReportedProcessIDs(ids...) + return tuo +} + +// RemoveReportedProcesses removes "reported_processes" edges to Process entities. +func (tuo *TaskUpdateOne) RemoveReportedProcesses(p ...*Process) *TaskUpdateOne { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return tuo.RemoveReportedProcessIDs(ids...) +} + // Where appends a list predicates to the TaskUpdate builder. func (tuo *TaskUpdateOne) Where(ps ...predicate.Task) *TaskUpdateOne { tuo.mutation.Where(ps...) @@ -746,6 +864,51 @@ func (tuo *TaskUpdateOne) sqlSave(ctx context.Context) (_node *Task, err error) } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if tuo.mutation.ReportedProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.RemovedReportedProcessesIDs(); len(nodes) > 0 && !tuo.mutation.ReportedProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.ReportedProcessesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: task.ReportedProcessesTable, + Columns: []string{task.ReportedProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &Task{config: tuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/tavern/internal/ent/tx.go b/tavern/internal/ent/tx.go index edcfd4313..21c7321f7 100644 --- a/tavern/internal/ent/tx.go +++ b/tavern/internal/ent/tx.go @@ -18,6 +18,8 @@ type Tx struct { File *FileClient // Host is the client for interacting with the Host builders. Host *HostClient + // Process is the client for interacting with the Process builders. + Process *ProcessClient // Quest is the client for interacting with the Quest builders. Quest *QuestClient // Tag is the client for interacting with the Tag builders. @@ -162,6 +164,7 @@ func (tx *Tx) init() { tx.Beacon = NewBeaconClient(tx.config) tx.File = NewFileClient(tx.config) tx.Host = NewHostClient(tx.config) + tx.Process = NewProcessClient(tx.config) tx.Quest = NewQuestClient(tx.config) tx.Tag = NewTagClient(tx.config) tx.Task = NewTaskClient(tx.config) diff --git a/tavern/internal/graphql/ent.resolvers.go b/tavern/internal/graphql/ent.resolvers.go index c785f34f9..ecc88ef1f 100644 --- a/tavern/internal/graphql/ent.resolvers.go +++ b/tavern/internal/graphql/ent.resolvers.go @@ -6,11 +6,17 @@ package graphql import ( "context" + "fmt" "realm.pub/tavern/internal/ent" "realm.pub/tavern/internal/graphql/generated" ) +// Pid is the resolver for the pid field. +func (r *processResolver) Pid(ctx context.Context, obj *ent.Process) (int, error) { + panic(fmt.Errorf("not implemented: Pid - pid")) +} + // Node is the resolver for the node field. func (r *queryResolver) Node(ctx context.Context, id int) (ent.Noder, error) { return r.client.Noder(ctx, id) @@ -21,7 +27,57 @@ func (r *queryResolver) Nodes(ctx context.Context, ids []int) ([]ent.Noder, erro return r.client.Noders(ctx, ids) } +// Pid is the resolver for the pid field. +func (r *processWhereInputResolver) Pid(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error { + panic(fmt.Errorf("not implemented: Pid - pid")) +} + +// PidNeq is the resolver for the pidNEQ field. +func (r *processWhereInputResolver) PidNeq(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error { + panic(fmt.Errorf("not implemented: PidNeq - pidNEQ")) +} + +// PidIn is the resolver for the pidIn field. +func (r *processWhereInputResolver) PidIn(ctx context.Context, obj *ent.ProcessWhereInput, data []int) error { + panic(fmt.Errorf("not implemented: PidIn - pidIn")) +} + +// PidNotIn is the resolver for the pidNotIn field. +func (r *processWhereInputResolver) PidNotIn(ctx context.Context, obj *ent.ProcessWhereInput, data []int) error { + panic(fmt.Errorf("not implemented: PidNotIn - pidNotIn")) +} + +// PidGt is the resolver for the pidGT field. +func (r *processWhereInputResolver) PidGt(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error { + panic(fmt.Errorf("not implemented: PidGt - pidGT")) +} + +// PidGte is the resolver for the pidGTE field. +func (r *processWhereInputResolver) PidGte(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error { + panic(fmt.Errorf("not implemented: PidGte - pidGTE")) +} + +// PidLt is the resolver for the pidLT field. +func (r *processWhereInputResolver) PidLt(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error { + panic(fmt.Errorf("not implemented: PidLt - pidLT")) +} + +// PidLte is the resolver for the pidLTE field. +func (r *processWhereInputResolver) PidLte(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error { + panic(fmt.Errorf("not implemented: PidLte - pidLTE")) +} + +// Process returns generated.ProcessResolver implementation. +func (r *Resolver) Process() generated.ProcessResolver { return &processResolver{r} } + // Query returns generated.QueryResolver implementation. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } +// ProcessWhereInput returns generated.ProcessWhereInputResolver implementation. +func (r *Resolver) ProcessWhereInput() generated.ProcessWhereInputResolver { + return &processWhereInputResolver{r} +} + +type processResolver struct{ *Resolver } type queryResolver struct{ *Resolver } +type processWhereInputResolver struct{ *Resolver } diff --git a/tavern/internal/graphql/generated/ent.generated.go b/tavern/internal/graphql/generated/ent.generated.go index 742d45809..cf4f29249 100644 --- a/tavern/internal/graphql/generated/ent.generated.go +++ b/tavern/internal/graphql/generated/ent.generated.go @@ -22,6 +22,9 @@ import ( // region ************************** generated!.gotpl ************************** +type ProcessResolver interface { + Pid(ctx context.Context, obj *ent.Process) (int, error) +} type QueryResolver interface { Node(ctx context.Context, id int) (ent.Noder, error) Nodes(ctx context.Context, ids []int) ([]ent.Noder, error) @@ -36,6 +39,17 @@ type QueryResolver interface { Me(ctx context.Context) (*ent.User, error) } +type ProcessWhereInputResolver interface { + Pid(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error + PidNeq(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error + PidIn(ctx context.Context, obj *ent.ProcessWhereInput, data []int) error + PidNotIn(ctx context.Context, obj *ent.ProcessWhereInput, data []int) error + PidGt(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error + PidGte(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error + PidLt(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error + PidLte(ctx context.Context, obj *ent.ProcessWhereInput, data *int) error +} + // endregion ************************** generated!.gotpl ************************** // region ***************************** args.gotpl ***************************** @@ -674,6 +688,8 @@ func (ec *executionContext) fieldContext_Beacon_tasks(ctx context.Context, field return ec.fieldContext_Task_quest(ctx, field) case "beacon": return ec.fieldContext_Task_beacon(ctx, field) + case "reportedProcesses": + return ec.fieldContext_Task_reportedProcesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Task", field.Name) }, @@ -1541,6 +1557,182 @@ func (ec *executionContext) fieldContext_PageInfo_endCursor(ctx context.Context, return fc, nil } +func (ec *executionContext) _Process_id(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_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.(int) + fc.Result = res + return ec.marshalNID2int(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Process_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + Field: field, + IsMethod: false, + 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) _Process_pid(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_pid(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.Process().Pid(rctx, obj) + }) + 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_Process_pid(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + Field: field, + IsMethod: true, + IsResolver: true, + 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) _Process_name(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_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_Process_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + 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) _Process_principal(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_principal(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.Principal, 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_Process_principal(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + 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) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_node(ctx, field) if err != nil { @@ -2981,6 +3173,8 @@ func (ec *executionContext) fieldContext_Quest_tasks(ctx context.Context, field return ec.fieldContext_Task_quest(ctx, field) case "beacon": return ec.fieldContext_Task_beacon(ctx, field) + case "reportedProcesses": + return ec.fieldContext_Task_reportedProcesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Task", field.Name) }, @@ -3741,6 +3935,57 @@ func (ec *executionContext) fieldContext_Task_beacon(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Task_reportedProcesses(ctx context.Context, field graphql.CollectedField, obj *ent.Task) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Task_reportedProcesses(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.ReportedProcesses(ctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*ent.Process) + fc.Result = res + return ec.marshalOProcess2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Task_reportedProcesses(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Task", + 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_Process_id(ctx, field) + case "pid": + return ec.fieldContext_Process_pid(ctx, field) + case "name": + return ec.fieldContext_Process_name(ctx, field) + case "principal": + return ec.fieldContext_Process_principal(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Process", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _TaskConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TaskConnection) (ret graphql.Marshaler) { fc, err := ec.fieldContext_TaskConnection_edges(ctx, field) if err != nil { @@ -3944,6 +4189,8 @@ func (ec *executionContext) fieldContext_TaskEdge_node(ctx context.Context, fiel return ec.fieldContext_Task_quest(ctx, field) case "beacon": return ec.fieldContext_Task_beacon(ctx, field) + case "reportedProcesses": + return ec.fieldContext_Task_reportedProcesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Task", field.Name) }, @@ -6960,56 +7207,14 @@ func (ec *executionContext) unmarshalInputHostWhereInput(ctx context.Context, ob return it, nil } -func (ec *executionContext) unmarshalInputQuestOrder(ctx context.Context, obj interface{}) (ent.QuestOrder, error) { - var it ent.QuestOrder - asMap := map[string]interface{}{} - for k, v := range obj.(map[string]interface{}) { - asMap[k] = v - } - - if _, present := asMap["direction"]; !present { - asMap["direction"] = "ASC" - } - - fieldsInOrder := [...]string{"direction", "field"} - for _, k := range fieldsInOrder { - v, ok := asMap[k] - if !ok { - continue - } - switch k { - case "direction": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) - data, err := ec.unmarshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚐOrderDirection(ctx, v) - if err != nil { - return it, err - } - it.Direction = data - case "field": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) - data, err := ec.unmarshalNQuestOrderField2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestOrderField(ctx, v) - if err != nil { - return it, err - } - it.Field = data - } - } - - return it, nil -} - -func (ec *executionContext) unmarshalInputQuestWhereInput(ctx context.Context, obj interface{}) (ent.QuestWhereInput, error) { - var it ent.QuestWhereInput +func (ec *executionContext) unmarshalInputProcessWhereInput(ctx context.Context, obj interface{}) (ent.ProcessWhereInput, error) { + var it ent.ProcessWhereInput asMap := map[string]interface{}{} for k, v := range obj.(map[string]interface{}) { asMap[k] = v } - fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "createdAt", "createdAtNEQ", "createdAtIn", "createdAtNotIn", "createdAtGT", "createdAtGTE", "createdAtLT", "createdAtLTE", "lastModifiedAt", "lastModifiedAtNEQ", "lastModifiedAtIn", "lastModifiedAtNotIn", "lastModifiedAtGT", "lastModifiedAtGTE", "lastModifiedAtLT", "lastModifiedAtLTE", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameEqualFold", "nameContainsFold", "parameters", "parametersNEQ", "parametersIn", "parametersNotIn", "parametersGT", "parametersGTE", "parametersLT", "parametersLTE", "parametersContains", "parametersHasPrefix", "parametersHasSuffix", "parametersIsNil", "parametersNotNil", "parametersEqualFold", "parametersContainsFold", "hasTome", "hasTomeWith", "hasBundle", "hasBundleWith", "hasTasks", "hasTasksWith", "hasCreator", "hasCreatorWith"} + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "pid", "pidNEQ", "pidIn", "pidNotIn", "pidGT", "pidGTE", "pidLT", "pidLTE", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameEqualFold", "nameContainsFold", "principal", "principalNEQ", "principalIn", "principalNotIn", "principalGT", "principalGTE", "principalLT", "principalLTE", "principalContains", "principalHasPrefix", "principalHasSuffix", "principalEqualFold", "principalContainsFold"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -7020,7 +7225,7 @@ func (ec *executionContext) unmarshalInputQuestWhereInput(ctx context.Context, o var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) - data, err := ec.unmarshalOQuestWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestWhereInput(ctx, v) + data, err := ec.unmarshalOProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx, v) if err != nil { return it, err } @@ -7029,7 +7234,7 @@ func (ec *executionContext) unmarshalInputQuestWhereInput(ctx context.Context, o var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - data, err := ec.unmarshalOQuestWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestWhereInputᚄ(ctx, v) + data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) if err != nil { return it, err } @@ -7038,7 +7243,7 @@ func (ec *executionContext) unmarshalInputQuestWhereInput(ctx context.Context, o var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - data, err := ec.unmarshalOQuestWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestWhereInputᚄ(ctx, v) + data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) if err != nil { return it, err } @@ -7115,17 +7320,500 @@ func (ec *executionContext) unmarshalInputQuestWhereInput(ctx context.Context, o return it, err } it.IDLTE = data - case "createdAt": + case "pid": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) - data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pid")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } - it.CreatedAt = data - case "createdAtNEQ": - var err error + if err = ec.resolvers.ProcessWhereInput().Pid(ctx, &it, data); err != nil { + return it, err + } + case "pidNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidNEQ")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidNeq(ctx, &it, data); err != nil { + return it, err + } + case "pidIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidIn")) + data, err := ec.unmarshalOInt2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidIn(ctx, &it, data); err != nil { + return it, err + } + case "pidNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidNotIn")) + data, err := ec.unmarshalOInt2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidNotIn(ctx, &it, data); err != nil { + return it, err + } + case "pidGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidGT")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidGt(ctx, &it, data); err != nil { + return it, err + } + case "pidGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidGTE")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidGte(ctx, &it, data); err != nil { + return it, err + } + case "pidLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidLT")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidLt(ctx, &it, data); err != nil { + return it, err + } + case "pidLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pidLTE")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.ProcessWhereInput().PidLte(ctx, &it, data); err != nil { + return it, err + } + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Name = data + case "nameNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNEQ")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameNEQ = data + case "nameIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameIn")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.NameIn = data + case "nameNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameNotIn")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.NameNotIn = data + case "nameGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGT")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameGT = data + case "nameGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameGTE")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameGTE = data + case "nameLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLT")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameLT = data + case "nameLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameLTE")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameLTE = data + case "nameContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContains")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameContains = data + case "nameHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasPrefix")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameHasPrefix = data + case "nameHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameHasSuffix")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameHasSuffix = data + case "nameEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameEqualFold")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameEqualFold = data + case "nameContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nameContainsFold")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NameContainsFold = data + case "principal": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principal")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Principal = data + case "principalNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalNEQ")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalNEQ = data + case "principalIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalIn")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.PrincipalIn = data + case "principalNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalNotIn")) + data, err := ec.unmarshalOString2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + it.PrincipalNotIn = data + case "principalGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalGT")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalGT = data + case "principalGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalGTE")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalGTE = data + case "principalLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalLT")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalLT = data + case "principalLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalLTE")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalLTE = data + case "principalContains": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalContains")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalContains = data + case "principalHasPrefix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalHasPrefix")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalHasPrefix = data + case "principalHasSuffix": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalHasSuffix")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalHasSuffix = data + case "principalEqualFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalEqualFold")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalEqualFold = data + case "principalContainsFold": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("principalContainsFold")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.PrincipalContainsFold = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputQuestOrder(ctx context.Context, obj interface{}) (ent.QuestOrder, error) { + var it ent.QuestOrder + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + if _, present := asMap["direction"]; !present { + asMap["direction"] = "ASC" + } + + fieldsInOrder := [...]string{"direction", "field"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "direction": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) + data, err := ec.unmarshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚐOrderDirection(ctx, v) + if err != nil { + return it, err + } + it.Direction = data + case "field": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) + data, err := ec.unmarshalNQuestOrderField2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestOrderField(ctx, v) + if err != nil { + return it, err + } + it.Field = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputQuestWhereInput(ctx context.Context, obj interface{}) (ent.QuestWhereInput, error) { + var it ent.QuestWhereInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "createdAt", "createdAtNEQ", "createdAtIn", "createdAtNotIn", "createdAtGT", "createdAtGTE", "createdAtLT", "createdAtLTE", "lastModifiedAt", "lastModifiedAtNEQ", "lastModifiedAtIn", "lastModifiedAtNotIn", "lastModifiedAtGT", "lastModifiedAtGTE", "lastModifiedAtLT", "lastModifiedAtLTE", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameEqualFold", "nameContainsFold", "parameters", "parametersNEQ", "parametersIn", "parametersNotIn", "parametersGT", "parametersGTE", "parametersLT", "parametersLTE", "parametersContains", "parametersHasPrefix", "parametersHasSuffix", "parametersIsNil", "parametersNotNil", "parametersEqualFold", "parametersContainsFold", "hasTome", "hasTomeWith", "hasBundle", "hasBundleWith", "hasTasks", "hasTasksWith", "hasCreator", "hasCreatorWith"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "not": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + data, err := ec.unmarshalOQuestWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestWhereInput(ctx, v) + if err != nil { + return it, err + } + it.Not = data + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + data, err := ec.unmarshalOQuestWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.And = data + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + data, err := ec.unmarshalOQuestWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.Or = data + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.ID = data + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDNEQ = data + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + it.IDIn = data + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + it.IDNotIn = data + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDGT = data + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDGTE = data + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDLT = data + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDLTE = data + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + it.CreatedAt = data + case "createdAtNEQ": + var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtNEQ")) data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) @@ -7970,7 +8658,7 @@ func (ec *executionContext) unmarshalInputTaskWhereInput(ctx context.Context, ob asMap[k] = v } - fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "createdAt", "createdAtNEQ", "createdAtIn", "createdAtNotIn", "createdAtGT", "createdAtGTE", "createdAtLT", "createdAtLTE", "lastModifiedAt", "lastModifiedAtNEQ", "lastModifiedAtIn", "lastModifiedAtNotIn", "lastModifiedAtGT", "lastModifiedAtGTE", "lastModifiedAtLT", "lastModifiedAtLTE", "claimedAt", "claimedAtNEQ", "claimedAtIn", "claimedAtNotIn", "claimedAtGT", "claimedAtGTE", "claimedAtLT", "claimedAtLTE", "claimedAtIsNil", "claimedAtNotNil", "execStartedAt", "execStartedAtNEQ", "execStartedAtIn", "execStartedAtNotIn", "execStartedAtGT", "execStartedAtGTE", "execStartedAtLT", "execStartedAtLTE", "execStartedAtIsNil", "execStartedAtNotNil", "execFinishedAt", "execFinishedAtNEQ", "execFinishedAtIn", "execFinishedAtNotIn", "execFinishedAtGT", "execFinishedAtGTE", "execFinishedAtLT", "execFinishedAtLTE", "execFinishedAtIsNil", "execFinishedAtNotNil", "output", "outputNEQ", "outputIn", "outputNotIn", "outputGT", "outputGTE", "outputLT", "outputLTE", "outputContains", "outputHasPrefix", "outputHasSuffix", "outputIsNil", "outputNotNil", "outputEqualFold", "outputContainsFold", "outputSize", "outputSizeNEQ", "outputSizeIn", "outputSizeNotIn", "outputSizeGT", "outputSizeGTE", "outputSizeLT", "outputSizeLTE", "error", "errorNEQ", "errorIn", "errorNotIn", "errorGT", "errorGTE", "errorLT", "errorLTE", "errorContains", "errorHasPrefix", "errorHasSuffix", "errorIsNil", "errorNotNil", "errorEqualFold", "errorContainsFold", "hasQuest", "hasQuestWith", "hasBeacon", "hasBeaconWith"} + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "createdAt", "createdAtNEQ", "createdAtIn", "createdAtNotIn", "createdAtGT", "createdAtGTE", "createdAtLT", "createdAtLTE", "lastModifiedAt", "lastModifiedAtNEQ", "lastModifiedAtIn", "lastModifiedAtNotIn", "lastModifiedAtGT", "lastModifiedAtGTE", "lastModifiedAtLT", "lastModifiedAtLTE", "claimedAt", "claimedAtNEQ", "claimedAtIn", "claimedAtNotIn", "claimedAtGT", "claimedAtGTE", "claimedAtLT", "claimedAtLTE", "claimedAtIsNil", "claimedAtNotNil", "execStartedAt", "execStartedAtNEQ", "execStartedAtIn", "execStartedAtNotIn", "execStartedAtGT", "execStartedAtGTE", "execStartedAtLT", "execStartedAtLTE", "execStartedAtIsNil", "execStartedAtNotNil", "execFinishedAt", "execFinishedAtNEQ", "execFinishedAtIn", "execFinishedAtNotIn", "execFinishedAtGT", "execFinishedAtGTE", "execFinishedAtLT", "execFinishedAtLTE", "execFinishedAtIsNil", "execFinishedAtNotNil", "output", "outputNEQ", "outputIn", "outputNotIn", "outputGT", "outputGTE", "outputLT", "outputLTE", "outputContains", "outputHasPrefix", "outputHasSuffix", "outputIsNil", "outputNotNil", "outputEqualFold", "outputContainsFold", "outputSize", "outputSizeNEQ", "outputSizeIn", "outputSizeNotIn", "outputSizeGT", "outputSizeGTE", "outputSizeLT", "outputSizeLTE", "error", "errorNEQ", "errorIn", "errorNotIn", "errorGT", "errorGTE", "errorLT", "errorLTE", "errorContains", "errorHasPrefix", "errorHasSuffix", "errorIsNil", "errorNotNil", "errorEqualFold", "errorContainsFold", "hasQuest", "hasQuestWith", "hasBeacon", "hasBeaconWith", "hasReportedProcesses", "hasReportedProcessesWith"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -8868,6 +9556,24 @@ func (ec *executionContext) unmarshalInputTaskWhereInput(ctx context.Context, ob return it, err } it.HasBeaconWith = data + case "hasReportedProcesses": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasReportedProcesses")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.HasReportedProcesses = data + case "hasReportedProcessesWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasReportedProcessesWith")) + data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.HasReportedProcessesWith = data } } @@ -10337,6 +11043,11 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._Host(ctx, sel, obj) + case *ent.Process: + if obj == nil { + return graphql.Null + } + return ec._Process(ctx, sel, obj) case *ent.Quest: if obj == nil { return graphql.Null @@ -10763,6 +11474,91 @@ func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, return out } +var processImplementors = []string{"Process", "Node"} + +func (ec *executionContext) _Process(ctx context.Context, sel ast.SelectionSet, obj *ent.Process) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, processImplementors) + + 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("Process") + case "id": + out.Values[i] = ec._Process_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "pid": + 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._Process_pid(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 "name": + out.Values[i] = ec._Process_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "principal": + out.Values[i] = ec._Process_principal(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + 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 queryImplementors = []string{"Query"} func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -11437,6 +12233,39 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "reportedProcesses": + 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._Task_reportedProcesses(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -12030,6 +12859,21 @@ func (ec *executionContext) marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚐPag return ec._PageInfo(ctx, sel, &v) } +func (ec *executionContext) marshalNProcess2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcess(ctx context.Context, sel ast.SelectionSet, v *ent.Process) 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._Process(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx context.Context, v interface{}) (*ent.ProcessWhereInput, error) { + res, err := ec.unmarshalInputProcessWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNQuest2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuestᚄ(ctx context.Context, sel ast.SelectionSet, v []*ent.Quest) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -12788,6 +13632,81 @@ func (ec *executionContext) marshalONode2realmᚗpubᚋtavernᚋinternalᚋent return ec._Node(ctx, sel, v) } +func (ec *executionContext) marshalOProcess2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessᚄ(ctx context.Context, sel ast.SelectionSet, v []*ent.Process) graphql.Marshaler { + if v == nil { + return graphql.Null + } + 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.marshalNProcess2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcess(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) unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx context.Context, v interface{}) ([]*ent.ProcessWhereInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*ent.ProcessWhereInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx context.Context, v interface{}) (*ent.ProcessWhereInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputProcessWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalOQuest2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐQuest(ctx context.Context, sel ast.SelectionSet, v *ent.Quest) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/tavern/internal/graphql/generated/mutation.generated.go b/tavern/internal/graphql/generated/mutation.generated.go index ee55d23b0..4dc19521b 100644 --- a/tavern/internal/graphql/generated/mutation.generated.go +++ b/tavern/internal/graphql/generated/mutation.generated.go @@ -752,6 +752,8 @@ func (ec *executionContext) fieldContext_Mutation_claimTasks(ctx context.Context return ec.fieldContext_Task_quest(ctx, field) case "beacon": return ec.fieldContext_Task_beacon(ctx, field) + case "reportedProcesses": + return ec.fieldContext_Task_reportedProcesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Task", field.Name) }, @@ -828,6 +830,8 @@ func (ec *executionContext) fieldContext_Mutation_submitTaskResult(ctx context.C return ec.fieldContext_Task_quest(ctx, field) case "beacon": return ec.fieldContext_Task_beacon(ctx, field) + case "reportedProcesses": + return ec.fieldContext_Task_reportedProcesses(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Task", field.Name) }, diff --git a/tavern/internal/graphql/generated/root_.generated.go b/tavern/internal/graphql/generated/root_.generated.go index 982852990..595e99bb3 100644 --- a/tavern/internal/graphql/generated/root_.generated.go +++ b/tavern/internal/graphql/generated/root_.generated.go @@ -36,7 +36,9 @@ type Config struct { type ResolverRoot interface { Mutation() MutationResolver + Process() ProcessResolver Query() QueryResolver + ProcessWhereInput() ProcessWhereInputResolver } type DirectiveRoot struct { @@ -96,6 +98,13 @@ type ComplexityRoot struct { StartCursor func(childComplexity int) int } + Process struct { + ID func(childComplexity int) int + Name func(childComplexity int) int + Pid func(childComplexity int) int + Principal func(childComplexity int) int + } + Query struct { Beacons func(childComplexity int, where *ent.BeaconWhereInput) int Files func(childComplexity int, where *ent.FileWhereInput) int @@ -130,17 +139,18 @@ type ComplexityRoot struct { } Task struct { - Beacon func(childComplexity int) int - ClaimedAt func(childComplexity int) int - CreatedAt func(childComplexity int) int - Error func(childComplexity int) int - ExecFinishedAt func(childComplexity int) int - ExecStartedAt func(childComplexity int) int - ID func(childComplexity int) int - LastModifiedAt func(childComplexity int) int - Output func(childComplexity int) int - OutputSize func(childComplexity int) int - Quest func(childComplexity int) int + Beacon func(childComplexity int) int + ClaimedAt func(childComplexity int) int + CreatedAt func(childComplexity int) int + Error func(childComplexity int) int + ExecFinishedAt func(childComplexity int) int + ExecStartedAt func(childComplexity int) int + ID func(childComplexity int) int + LastModifiedAt func(childComplexity int) int + Output func(childComplexity int) int + OutputSize func(childComplexity int) int + Quest func(childComplexity int) int + ReportedProcesses func(childComplexity int) int } TaskConnection struct { @@ -497,6 +507,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PageInfo.StartCursor(childComplexity), true + case "Process.id": + if e.complexity.Process.ID == nil { + break + } + + return e.complexity.Process.ID(childComplexity), true + + case "Process.name": + if e.complexity.Process.Name == nil { + break + } + + return e.complexity.Process.Name(childComplexity), true + + case "Process.pid": + if e.complexity.Process.Pid == nil { + break + } + + return e.complexity.Process.Pid(childComplexity), true + + case "Process.principal": + if e.complexity.Process.Principal == nil { + break + } + + return e.complexity.Process.Principal(childComplexity), true + case "Query.beacons": if e.complexity.Query.Beacons == nil { break @@ -792,6 +830,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Task.Quest(childComplexity), true + case "Task.reportedProcesses": + if e.complexity.Task.ReportedProcesses == nil { + break + } + + return e.complexity.Task.ReportedProcesses(childComplexity), true + case "TaskConnection.edges": if e.complexity.TaskConnection.Edges == nil { break @@ -936,6 +981,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputFileWhereInput, ec.unmarshalInputHostOrder, ec.unmarshalInputHostWhereInput, + ec.unmarshalInputProcessWhereInput, ec.unmarshalInputQuestOrder, ec.unmarshalInputQuestWhereInput, ec.unmarshalInputSubmitTaskResultInput, @@ -1489,6 +1535,70 @@ type PageInfo { """When paginating forwards, the cursor to continue.""" endCursor: Cursor } +type Process implements Node { + id: ID! + """ID of the process.""" + pid: Int! + """The name of the process.""" + name: String! + """The user the process is running as.""" + principal: String! +} +""" +ProcessWhereInput is used for filtering Process objects. +Input was generated by ent. +""" +input ProcessWhereInput { + not: ProcessWhereInput + and: [ProcessWhereInput!] + or: [ProcessWhereInput!] + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + """pid field predicates""" + pid: Int + pidNEQ: Int + pidIn: [Int!] + pidNotIn: [Int!] + pidGT: Int + pidGTE: Int + pidLT: Int + pidLTE: Int + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + """principal field predicates""" + principal: String + principalNEQ: String + principalIn: [String!] + principalNotIn: [String!] + principalGT: String + principalGTE: String + principalLT: String + principalLTE: String + principalContains: String + principalHasPrefix: String + principalHasSuffix: String + principalEqualFold: String + principalContainsFold: String +} type Query { """Fetches an object given its ID.""" node( @@ -1695,6 +1805,8 @@ type Task implements Node { error: String quest: Quest! beacon: Beacon! + """Processes that have been reported by this task.""" + reportedProcesses: [Process!] } """A connection to a list of items.""" type TaskConnection { @@ -1843,6 +1955,9 @@ input TaskWhereInput { """beacon edge predicates""" hasBeacon: Boolean hasBeaconWith: [BeaconWhereInput!] + """reported_processes edge predicates""" + hasReportedProcesses: Boolean + hasReportedProcessesWith: [ProcessWhereInput!] } type Tome implements Node { id: ID! diff --git a/tavern/internal/graphql/gqlgen.yml b/tavern/internal/graphql/gqlgen.yml index 1d8469bac..e6a203251 100644 --- a/tavern/internal/graphql/gqlgen.yml +++ b/tavern/internal/graphql/gqlgen.yml @@ -33,6 +33,7 @@ autobind: - realm.pub/tavern/internal/ent/quest - realm.pub/tavern/internal/ent/task - realm.pub/tavern/internal/ent/tome + - realm.pub/tavern/internal/ent/process struct_tag: json diff --git a/tavern/internal/graphql/schema.graphql b/tavern/internal/graphql/schema.graphql index 6fb72a042..d51b3b058 100644 --- a/tavern/internal/graphql/schema.graphql +++ b/tavern/internal/graphql/schema.graphql @@ -439,6 +439,70 @@ type PageInfo { """When paginating forwards, the cursor to continue.""" endCursor: Cursor } +type Process implements Node { + id: ID! + """ID of the process.""" + pid: Int! + """The name of the process.""" + name: String! + """The user the process is running as.""" + principal: String! +} +""" +ProcessWhereInput is used for filtering Process objects. +Input was generated by ent. +""" +input ProcessWhereInput { + not: ProcessWhereInput + and: [ProcessWhereInput!] + or: [ProcessWhereInput!] + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + """pid field predicates""" + pid: Int + pidNEQ: Int + pidIn: [Int!] + pidNotIn: [Int!] + pidGT: Int + pidGTE: Int + pidLT: Int + pidLTE: Int + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + """principal field predicates""" + principal: String + principalNEQ: String + principalIn: [String!] + principalNotIn: [String!] + principalGT: String + principalGTE: String + principalLT: String + principalLTE: String + principalContains: String + principalHasPrefix: String + principalHasSuffix: String + principalEqualFold: String + principalContainsFold: String +} type Query { """Fetches an object given its ID.""" node( @@ -645,6 +709,8 @@ type Task implements Node { error: String quest: Quest! beacon: Beacon! + """Processes that have been reported by this task.""" + reportedProcesses: [Process!] } """A connection to a list of items.""" type TaskConnection { @@ -793,6 +859,9 @@ input TaskWhereInput { """beacon edge predicates""" hasBeacon: Boolean hasBeaconWith: [BeaconWhereInput!] + """reported_processes edge predicates""" + hasReportedProcesses: Boolean + hasReportedProcessesWith: [ProcessWhereInput!] } type Tome implements Node { id: ID! diff --git a/tavern/internal/graphql/schema/ent.graphql b/tavern/internal/graphql/schema/ent.graphql index 0037981e3..0b67f9e6a 100644 --- a/tavern/internal/graphql/schema/ent.graphql +++ b/tavern/internal/graphql/schema/ent.graphql @@ -434,6 +434,70 @@ type PageInfo { """When paginating forwards, the cursor to continue.""" endCursor: Cursor } +type Process implements Node { + id: ID! + """ID of the process.""" + pid: Int! + """The name of the process.""" + name: String! + """The user the process is running as.""" + principal: String! +} +""" +ProcessWhereInput is used for filtering Process objects. +Input was generated by ent. +""" +input ProcessWhereInput { + not: ProcessWhereInput + and: [ProcessWhereInput!] + or: [ProcessWhereInput!] + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + """pid field predicates""" + pid: Int + pidNEQ: Int + pidIn: [Int!] + pidNotIn: [Int!] + pidGT: Int + pidGTE: Int + pidLT: Int + pidLTE: Int + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + """principal field predicates""" + principal: String + principalNEQ: String + principalIn: [String!] + principalNotIn: [String!] + principalGT: String + principalGTE: String + principalLT: String + principalLTE: String + principalContains: String + principalHasPrefix: String + principalHasSuffix: String + principalEqualFold: String + principalContainsFold: String +} type Query { """Fetches an object given its ID.""" node( @@ -640,6 +704,8 @@ type Task implements Node { error: String quest: Quest! beacon: Beacon! + """Processes that have been reported by this task.""" + reportedProcesses: [Process!] } """A connection to a list of items.""" type TaskConnection { @@ -788,6 +854,9 @@ input TaskWhereInput { """beacon edge predicates""" hasBeacon: Boolean hasBeaconWith: [BeaconWhereInput!] + """reported_processes edge predicates""" + hasReportedProcesses: Boolean + hasReportedProcessesWith: [ProcessWhereInput!] } type Tome implements Node { id: ID! diff --git a/tavern/internal/www/schema.graphql b/tavern/internal/www/schema.graphql index 6fb72a042..d51b3b058 100644 --- a/tavern/internal/www/schema.graphql +++ b/tavern/internal/www/schema.graphql @@ -439,6 +439,70 @@ type PageInfo { """When paginating forwards, the cursor to continue.""" endCursor: Cursor } +type Process implements Node { + id: ID! + """ID of the process.""" + pid: Int! + """The name of the process.""" + name: String! + """The user the process is running as.""" + principal: String! +} +""" +ProcessWhereInput is used for filtering Process objects. +Input was generated by ent. +""" +input ProcessWhereInput { + not: ProcessWhereInput + and: [ProcessWhereInput!] + or: [ProcessWhereInput!] + """id field predicates""" + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + """pid field predicates""" + pid: Int + pidNEQ: Int + pidIn: [Int!] + pidNotIn: [Int!] + pidGT: Int + pidGTE: Int + pidLT: Int + pidLTE: Int + """name field predicates""" + name: String + nameNEQ: String + nameIn: [String!] + nameNotIn: [String!] + nameGT: String + nameGTE: String + nameLT: String + nameLTE: String + nameContains: String + nameHasPrefix: String + nameHasSuffix: String + nameEqualFold: String + nameContainsFold: String + """principal field predicates""" + principal: String + principalNEQ: String + principalIn: [String!] + principalNotIn: [String!] + principalGT: String + principalGTE: String + principalLT: String + principalLTE: String + principalContains: String + principalHasPrefix: String + principalHasSuffix: String + principalEqualFold: String + principalContainsFold: String +} type Query { """Fetches an object given its ID.""" node( @@ -645,6 +709,8 @@ type Task implements Node { error: String quest: Quest! beacon: Beacon! + """Processes that have been reported by this task.""" + reportedProcesses: [Process!] } """A connection to a list of items.""" type TaskConnection { @@ -793,6 +859,9 @@ input TaskWhereInput { """beacon edge predicates""" hasBeacon: Boolean hasBeaconWith: [BeaconWhereInput!] + """reported_processes edge predicates""" + hasReportedProcesses: Boolean + hasReportedProcessesWith: [ProcessWhereInput!] } type Tome implements Node { id: ID! From d6cf1109c54bff27d2b2d4aadf1ba52f6155f201 Mon Sep 17 00:00:00 2001 From: KCarretto Date: Tue, 23 Jan 2024 00:06:19 +0000 Subject: [PATCH 2/3] Added API --- tavern/internal/c2/api_report_process_list.go | 84 ++ .../c2/api_report_process_list_test.go | 135 +++ tavern/internal/ent/client.go | 48 ++ tavern/internal/ent/gql_collection.go | 64 ++ tavern/internal/ent/gql_edge.go | 28 + tavern/internal/ent/gql_mutation_input.go | 28 +- tavern/internal/ent/gql_pagination.go | 101 +++ tavern/internal/ent/gql_where_input.go | 134 +++ tavern/internal/ent/host.go | 49 +- tavern/internal/ent/host/host.go | 30 + tavern/internal/ent/host/where.go | 23 + tavern/internal/ent/host_create.go | 32 + tavern/internal/ent/host_query.go | 133 ++- tavern/internal/ent/host_update.go | 163 ++++ tavern/internal/ent/migrate/schema.go | 26 +- tavern/internal/ent/mutation.go | 389 ++++++++- tavern/internal/ent/process.go | 103 ++- tavern/internal/ent/process/process.go | 73 ++ tavern/internal/ent/process/where.go | 139 ++++ tavern/internal/ent/process_create.go | 179 +++- tavern/internal/ent/process_query.go | 171 +++- tavern/internal/ent/process_update.go | 235 ++++++ tavern/internal/ent/runtime/runtime.go | 13 + tavern/internal/ent/schema/host.go | 2 + tavern/internal/ent/schema/process.go | 32 +- .../graphql/generated/ent.generated.go | 785 +++++++++++++++++- .../graphql/generated/mutation.generated.go | 2 + .../graphql/generated/root_.generated.go | 103 ++- tavern/internal/graphql/schema.graphql | 54 ++ tavern/internal/graphql/schema/ent.graphql | 54 ++ tavern/internal/www/schema.graphql | 54 ++ 31 files changed, 3321 insertions(+), 145 deletions(-) create mode 100644 tavern/internal/c2/api_report_process_list.go create mode 100644 tavern/internal/c2/api_report_process_list_test.go diff --git a/tavern/internal/c2/api_report_process_list.go b/tavern/internal/c2/api_report_process_list.go new file mode 100644 index 000000000..2a990d587 --- /dev/null +++ b/tavern/internal/c2/api_report_process_list.go @@ -0,0 +1,84 @@ +package c2 + +import ( + "context" + "fmt" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "realm.pub/tavern/internal/c2/c2pb" + "realm.pub/tavern/internal/ent" +) + +func (srv *Server) ReportProcessList(ctx context.Context, req *c2pb.ReportProcessListRequest) (*c2pb.ReportProcessListResponse, error) { + // Validate Arguments + if req.TaskId == 0 { + return nil, status.Errorf(codes.InvalidArgument, "must provide task id") + } + if len(req.List) < 1 { + return nil, status.Errorf(codes.InvalidArgument, "must provide process list") + } + + // Load Task + task, err := srv.graph.Task.Get(ctx, int(req.TaskId)) + if ent.IsNotFound(err) { + return nil, status.Errorf(codes.NotFound, "no task found") + } + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load task") + } + + // Load Host + host, err := task.QueryBeacon().QueryHost().Only(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load host") + } + + // Prepare Transaction + tx, err := srv.graph.Tx(ctx) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to initialize transaction: %v", err) + } + txGraph := tx.Client() + + // Rollback transaction if we panic + defer func() { + if v := recover(); v != nil { + tx.Rollback() + panic(v) + } + }() + + // Create Processes + builders := make([]*ent.ProcessCreate, 0, len(req.List)) + for _, proc := range req.List { + builders = append(builders, + txGraph.Process.Create(). + SetHostID(host.ID). + SetTaskID(task.ID). + SetPid(proc.Pid). + SetName(proc.Name). + SetPrincipal(proc.Principal), + ) + } + processList, err := txGraph.Process.CreateBulk(builders...).Save(ctx) + if err != nil { + return nil, rollback(tx, fmt.Errorf("failed to create process list: %w", err)) + } + + // Set new process list for host + _, err = txGraph.Host.UpdateOne(host). + ClearProcesses(). + AddProcesses(processList...). + Save(ctx) + if err != nil { + return nil, rollback(tx, fmt.Errorf("failed to set new host process list: %w", err)) + } + + // Commit the transaction + if err := tx.Commit(); err != nil { + return nil, rollback(tx, fmt.Errorf("failed to commit transaction: %w", err)) + } + + return &c2pb.ReportProcessListResponse{}, nil +} diff --git a/tavern/internal/c2/api_report_process_list_test.go b/tavern/internal/c2/api_report_process_list_test.go new file mode 100644 index 000000000..716c75a25 --- /dev/null +++ b/tavern/internal/c2/api_report_process_list_test.go @@ -0,0 +1,135 @@ +package c2_test + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/testing/protocmp" + "realm.pub/tavern/internal/c2/c2pb" + "realm.pub/tavern/internal/c2/c2test" + "realm.pub/tavern/internal/ent" +) + +func TestReportProcessList(t *testing.T) { + // Setup Dependencies + ctx := context.Background() + client, graph, close := c2test.New(t) + defer close() + + // Test Data + existingBeacon := c2test.NewRandomBeacon(ctx, graph) + existingTask := c2test.NewRandomAssignedTask(ctx, graph, existingBeacon.Identifier) + existingHost := existingBeacon.QueryHost().OnlyX(ctx) + + // Test Cases + tests := []struct { + name string + host *ent.Host + task *ent.Task + req *c2pb.ReportProcessListRequest + + wantResp *c2pb.ReportProcessListResponse + wantCode codes.Code + wantHostPIDs []uint64 + wantTaskPIDs []uint64 + }{ + { + name: "New_List", + host: existingHost, + task: existingTask, + req: &c2pb.ReportProcessListRequest{ + TaskId: int64(existingTask.ID), + List: []*c2pb.Process{ + {Pid: 1, Name: "systemd", Principal: "root"}, + {Pid: 2321, Name: "/bin/sh", Principal: "root"}, + {Pid: 4505, Name: "/usr/bin/sshd", Principal: "root"}, + }, + }, + wantResp: &c2pb.ReportProcessListResponse{}, + wantCode: codes.OK, + wantHostPIDs: []uint64{1, 2321, 4505}, + wantTaskPIDs: []uint64{1, 2321, 4505}, + }, + { + name: "Updated_List", + host: existingHost, + task: existingTask, + req: &c2pb.ReportProcessListRequest{ + TaskId: int64(existingTask.ID), + List: []*c2pb.Process{ + {Pid: 1, Name: "systemd", Principal: "root"}, + {Pid: 4505, Name: "/usr/bin/sshd", Principal: "root"}, + {Pid: 4809, Name: "/usr/bin/nginx", Principal: "root"}, + }, + }, + wantResp: &c2pb.ReportProcessListResponse{}, + wantCode: codes.OK, + wantHostPIDs: []uint64{1, 4505, 4809}, + wantTaskPIDs: []uint64{1, 2321, 4505, 1, 4505, 4809}, + }, + { + name: "No_TaskID", + host: existingHost, + task: existingTask, + req: &c2pb.ReportProcessListRequest{ + List: []*c2pb.Process{ + {Pid: 1, Name: "systemd", Principal: "root"}, + }, + }, + wantResp: nil, + wantCode: codes.InvalidArgument, + }, + { + name: "No_Processes", + host: existingHost, + task: existingTask, + req: &c2pb.ReportProcessListRequest{ + TaskId: int64(existingTask.ID), + List: []*c2pb.Process{}, + }, + wantResp: nil, + wantCode: codes.InvalidArgument, + }, + } + + // Run Tests + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + // gRPC + resp, err := client.ReportProcessList(ctx, tc.req) + + // Assert Response Code + require.Equal(t, tc.wantCode.String(), status.Code(err).String(), err) + if status.Code(err) != codes.OK { + // Do not continue if we expected error code + return + } + + // Assert Response + if diff := cmp.Diff(tc.wantResp, resp, protocmp.Transform()); diff != "" { + t.Errorf("invalid response (-want +got): %v", diff) + } + + // Assert Task Processes + var taskPIDs []uint64 + taskProcessList := tc.task.QueryReportedProcesses().AllX(ctx) + for _, proc := range taskProcessList { + taskPIDs = append(taskPIDs, proc.Pid) + } + assert.ElementsMatch(t, tc.wantTaskPIDs, taskPIDs) + + // Assert Host Processes + var hostPIDs []uint64 + hostProcessList := tc.host.QueryProcesses().AllX(ctx) + for _, proc := range hostProcessList { + hostPIDs = append(hostPIDs, proc.Pid) + } + assert.ElementsMatch(t, tc.wantHostPIDs, hostPIDs) + }) + } +} diff --git a/tavern/internal/ent/client.go b/tavern/internal/ent/client.go index bede438eb..f0d35c1b7 100644 --- a/tavern/internal/ent/client.go +++ b/tavern/internal/ent/client.go @@ -721,6 +721,22 @@ func (c *HostClient) QueryBeacons(h *Host) *BeaconQuery { return query } +// QueryProcesses queries the processes edge of a Host. +func (c *HostClient) QueryProcesses(h *Host) *ProcessQuery { + query := (&ProcessClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := h.ID + step := sqlgraph.NewStep( + sqlgraph.From(host.Table, host.FieldID, id), + sqlgraph.To(process.Table, process.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, host.ProcessesTable, host.ProcessesColumn), + ) + fromV = sqlgraph.Neighbors(h.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *HostClient) Hooks() []Hook { return c.hooks.Host @@ -854,6 +870,38 @@ func (c *ProcessClient) GetX(ctx context.Context, id int) *Process { return obj } +// QueryHost queries the host edge of a Process. +func (c *ProcessClient) QueryHost(pr *Process) *HostQuery { + query := (&HostClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := pr.ID + step := sqlgraph.NewStep( + sqlgraph.From(process.Table, process.FieldID, id), + sqlgraph.To(host.Table, host.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, process.HostTable, process.HostColumn), + ) + fromV = sqlgraph.Neighbors(pr.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryTask queries the task edge of a Process. +func (c *ProcessClient) QueryTask(pr *Process) *TaskQuery { + query := (&TaskClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := pr.ID + step := sqlgraph.NewStep( + sqlgraph.From(process.Table, process.FieldID, id), + sqlgraph.To(task.Table, task.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, process.TaskTable, process.TaskColumn), + ) + fromV = sqlgraph.Neighbors(pr.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *ProcessClient) Hooks() []Hook { return c.hooks.Process diff --git a/tavern/internal/ent/gql_collection.go b/tavern/internal/ent/gql_collection.go index 0098cd5fa..08b1282af 100644 --- a/tavern/internal/ent/gql_collection.go +++ b/tavern/internal/ent/gql_collection.go @@ -321,6 +321,18 @@ func (h *HostQuery) collectField(ctx context.Context, opCtx *graphql.OperationCo h.WithNamedBeacons(alias, func(wq *BeaconQuery) { *wq = *query }) + case "processes": + var ( + alias = field.Alias + path = append(path, alias) + query = (&ProcessClient{config: h.config}).Query() + ) + if err := query.collectField(ctx, opCtx, field, path, satisfies...); err != nil { + return err + } + h.WithNamedProcesses(alias, func(wq *ProcessQuery) { + *wq = *query + }) case "identifier": if _, ok := fieldSeen[host.FieldIdentifier]; !ok { selectedFields = append(selectedFields, host.FieldIdentifier) @@ -430,6 +442,36 @@ func (pr *ProcessQuery) collectField(ctx context.Context, opCtx *graphql.Operati ) for _, field := range graphql.CollectFields(opCtx, collected.Selections, satisfies) { switch field.Name { + case "host": + var ( + alias = field.Alias + path = append(path, alias) + query = (&HostClient{config: pr.config}).Query() + ) + if err := query.collectField(ctx, opCtx, field, path, satisfies...); err != nil { + return err + } + pr.withHost = query + case "task": + var ( + alias = field.Alias + path = append(path, alias) + query = (&TaskClient{config: pr.config}).Query() + ) + if err := query.collectField(ctx, opCtx, field, path, satisfies...); err != nil { + return err + } + pr.withTask = query + case "createdAt": + if _, ok := fieldSeen[process.FieldCreatedAt]; !ok { + selectedFields = append(selectedFields, process.FieldCreatedAt) + fieldSeen[process.FieldCreatedAt] = struct{}{} + } + case "lastModifiedAt": + if _, ok := fieldSeen[process.FieldLastModifiedAt]; !ok { + selectedFields = append(selectedFields, process.FieldLastModifiedAt) + fieldSeen[process.FieldLastModifiedAt] = struct{}{} + } case "pid": if _, ok := fieldSeen[process.FieldPid]; !ok { selectedFields = append(selectedFields, process.FieldPid) @@ -480,6 +522,28 @@ func newProcessPaginateArgs(rv map[string]any) *processPaginateArgs { if v := rv[beforeField]; v != nil { args.before = v.(*Cursor) } + if v, ok := rv[orderByField]; ok { + switch v := v.(type) { + case map[string]any: + var ( + err1, err2 error + order = &ProcessOrder{Field: &ProcessOrderField{}, Direction: entgql.OrderDirectionAsc} + ) + if d, ok := v[directionField]; ok { + err1 = order.Direction.UnmarshalGQL(d) + } + if f, ok := v[fieldField]; ok { + err2 = order.Field.UnmarshalGQL(f) + } + if err1 == nil && err2 == nil { + args.opts = append(args.opts, WithProcessOrder(order)) + } + case *ProcessOrder: + if v != nil { + args.opts = append(args.opts, WithProcessOrder(v)) + } + } + } if v, ok := rv[whereField].(*ProcessWhereInput); ok { args.opts = append(args.opts, WithProcessFilter(v.Filter)) } diff --git a/tavern/internal/ent/gql_edge.go b/tavern/internal/ent/gql_edge.go index e39fab3dc..311a30c75 100644 --- a/tavern/internal/ent/gql_edge.go +++ b/tavern/internal/ent/gql_edge.go @@ -64,6 +64,34 @@ func (h *Host) Beacons(ctx context.Context) (result []*Beacon, err error) { return result, err } +func (h *Host) Processes(ctx context.Context) (result []*Process, err error) { + if fc := graphql.GetFieldContext(ctx); fc != nil && fc.Field.Alias != "" { + result, err = h.NamedProcesses(graphql.GetFieldContext(ctx).Field.Alias) + } else { + result, err = h.Edges.ProcessesOrErr() + } + if IsNotLoaded(err) { + result, err = h.QueryProcesses().All(ctx) + } + return result, err +} + +func (pr *Process) Host(ctx context.Context) (*Host, error) { + result, err := pr.Edges.HostOrErr() + if IsNotLoaded(err) { + result, err = pr.QueryHost().Only(ctx) + } + return result, err +} + +func (pr *Process) Task(ctx context.Context) (*Task, error) { + result, err := pr.Edges.TaskOrErr() + if IsNotLoaded(err) { + result, err = pr.QueryTask().Only(ctx) + } + return result, err +} + func (q *Quest) Tome(ctx context.Context) (*Tome, error) { result, err := q.Edges.TomeOrErr() if IsNotLoaded(err) { diff --git a/tavern/internal/ent/gql_mutation_input.go b/tavern/internal/ent/gql_mutation_input.go index e33faf852..85e45c3e7 100644 --- a/tavern/internal/ent/gql_mutation_input.go +++ b/tavern/internal/ent/gql_mutation_input.go @@ -32,14 +32,17 @@ func (c *BeaconUpdateOne) SetInput(i UpdateBeaconInput) *BeaconUpdateOne { // UpdateHostInput represents a mutation input for updating hosts. type UpdateHostInput struct { - ClearName bool - Name *string - ClearTags bool - AddTagIDs []int - RemoveTagIDs []int - ClearBeacons bool - AddBeaconIDs []int - RemoveBeaconIDs []int + ClearName bool + Name *string + ClearTags bool + AddTagIDs []int + RemoveTagIDs []int + ClearBeacons bool + AddBeaconIDs []int + RemoveBeaconIDs []int + ClearProcesses bool + AddProcessIDs []int + RemoveProcessIDs []int } // Mutate applies the UpdateHostInput on the HostMutation builder. @@ -68,6 +71,15 @@ func (i *UpdateHostInput) Mutate(m *HostMutation) { if v := i.RemoveBeaconIDs; len(v) > 0 { m.RemoveBeaconIDs(v...) } + if i.ClearProcesses { + m.ClearProcesses() + } + if v := i.AddProcessIDs; len(v) > 0 { + m.AddProcessIDs(v...) + } + if v := i.RemoveProcessIDs; len(v) > 0 { + m.RemoveProcessIDs(v...) + } } // SetInput applies the change-set in the UpdateHostInput on the HostUpdate builder. diff --git a/tavern/internal/ent/gql_pagination.go b/tavern/internal/ent/gql_pagination.go index d10ce0187..c19105491 100644 --- a/tavern/internal/ent/gql_pagination.go +++ b/tavern/internal/ent/gql_pagination.go @@ -1262,6 +1262,107 @@ func (pr *ProcessQuery) Paginate( return conn, nil } +var ( + // ProcessOrderFieldCreatedAt orders Process by created_at. + ProcessOrderFieldCreatedAt = &ProcessOrderField{ + Value: func(pr *Process) (ent.Value, error) { + return pr.CreatedAt, nil + }, + column: process.FieldCreatedAt, + toTerm: process.ByCreatedAt, + toCursor: func(pr *Process) Cursor { + return Cursor{ + ID: pr.ID, + Value: pr.CreatedAt, + } + }, + } + // ProcessOrderFieldLastModifiedAt orders Process by last_modified_at. + ProcessOrderFieldLastModifiedAt = &ProcessOrderField{ + Value: func(pr *Process) (ent.Value, error) { + return pr.LastModifiedAt, nil + }, + column: process.FieldLastModifiedAt, + toTerm: process.ByLastModifiedAt, + toCursor: func(pr *Process) Cursor { + return Cursor{ + ID: pr.ID, + Value: pr.LastModifiedAt, + } + }, + } + // ProcessOrderFieldPid orders Process by pid. + ProcessOrderFieldPid = &ProcessOrderField{ + Value: func(pr *Process) (ent.Value, error) { + return pr.Pid, nil + }, + column: process.FieldPid, + toTerm: process.ByPid, + toCursor: func(pr *Process) Cursor { + return Cursor{ + ID: pr.ID, + Value: pr.Pid, + } + }, + } + // ProcessOrderFieldName orders Process by name. + ProcessOrderFieldName = &ProcessOrderField{ + Value: func(pr *Process) (ent.Value, error) { + return pr.Name, nil + }, + column: process.FieldName, + toTerm: process.ByName, + toCursor: func(pr *Process) Cursor { + return Cursor{ + ID: pr.ID, + Value: pr.Name, + } + }, + } +) + +// String implement fmt.Stringer interface. +func (f ProcessOrderField) String() string { + var str string + switch f.column { + case ProcessOrderFieldCreatedAt.column: + str = "CREATED_AT" + case ProcessOrderFieldLastModifiedAt.column: + str = "LAST_MODIFIED_AT" + case ProcessOrderFieldPid.column: + str = "PROCESS_ID" + case ProcessOrderFieldName.column: + str = "NAME" + } + return str +} + +// MarshalGQL implements graphql.Marshaler interface. +func (f ProcessOrderField) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(f.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (f *ProcessOrderField) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("ProcessOrderField %T must be a string", v) + } + switch str { + case "CREATED_AT": + *f = *ProcessOrderFieldCreatedAt + case "LAST_MODIFIED_AT": + *f = *ProcessOrderFieldLastModifiedAt + case "PROCESS_ID": + *f = *ProcessOrderFieldPid + case "NAME": + *f = *ProcessOrderFieldName + default: + return fmt.Errorf("%s is not a valid ProcessOrderField", str) + } + return nil +} + // ProcessOrderField defines the ordering field of Process. type ProcessOrderField struct { // Value extracts the ordering value from the given Process. diff --git a/tavern/internal/ent/gql_where_input.go b/tavern/internal/ent/gql_where_input.go index 6cd226237..03d381f4d 100644 --- a/tavern/internal/ent/gql_where_input.go +++ b/tavern/internal/ent/gql_where_input.go @@ -950,6 +950,10 @@ type HostWhereInput struct { // "beacons" edge predicates. HasBeacons *bool `json:"hasBeacons,omitempty"` HasBeaconsWith []*BeaconWhereInput `json:"hasBeaconsWith,omitempty"` + + // "processes" edge predicates. + HasProcesses *bool `json:"hasProcesses,omitempty"` + HasProcessesWith []*ProcessWhereInput `json:"hasProcessesWith,omitempty"` } // AddPredicates adds custom predicates to the where input to be used during the filtering phase. @@ -1255,6 +1259,24 @@ func (i *HostWhereInput) P() (predicate.Host, error) { } predicates = append(predicates, host.HasBeaconsWith(with...)) } + if i.HasProcesses != nil { + p := host.HasProcesses() + if !*i.HasProcesses { + p = host.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasProcessesWith) > 0 { + with := make([]predicate.Process, 0, len(i.HasProcessesWith)) + for _, w := range i.HasProcessesWith { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'HasProcessesWith'", err) + } + with = append(with, p) + } + predicates = append(predicates, host.HasProcessesWith(with...)) + } switch len(predicates) { case 0: return nil, ErrEmptyHostWhereInput @@ -1282,6 +1304,26 @@ type ProcessWhereInput struct { IDLT *int `json:"idLT,omitempty"` IDLTE *int `json:"idLTE,omitempty"` + // "created_at" field predicates. + CreatedAt *time.Time `json:"createdAt,omitempty"` + CreatedAtNEQ *time.Time `json:"createdAtNEQ,omitempty"` + CreatedAtIn []time.Time `json:"createdAtIn,omitempty"` + CreatedAtNotIn []time.Time `json:"createdAtNotIn,omitempty"` + CreatedAtGT *time.Time `json:"createdAtGT,omitempty"` + CreatedAtGTE *time.Time `json:"createdAtGTE,omitempty"` + CreatedAtLT *time.Time `json:"createdAtLT,omitempty"` + CreatedAtLTE *time.Time `json:"createdAtLTE,omitempty"` + + // "last_modified_at" field predicates. + LastModifiedAt *time.Time `json:"lastModifiedAt,omitempty"` + LastModifiedAtNEQ *time.Time `json:"lastModifiedAtNEQ,omitempty"` + LastModifiedAtIn []time.Time `json:"lastModifiedAtIn,omitempty"` + LastModifiedAtNotIn []time.Time `json:"lastModifiedAtNotIn,omitempty"` + LastModifiedAtGT *time.Time `json:"lastModifiedAtGT,omitempty"` + LastModifiedAtGTE *time.Time `json:"lastModifiedAtGTE,omitempty"` + LastModifiedAtLT *time.Time `json:"lastModifiedAtLT,omitempty"` + LastModifiedAtLTE *time.Time `json:"lastModifiedAtLTE,omitempty"` + // "pid" field predicates. Pid *uint64 `json:"pid,omitempty"` PidNEQ *uint64 `json:"pidNEQ,omitempty"` @@ -1321,6 +1363,14 @@ type ProcessWhereInput struct { PrincipalHasSuffix *string `json:"principalHasSuffix,omitempty"` PrincipalEqualFold *string `json:"principalEqualFold,omitempty"` PrincipalContainsFold *string `json:"principalContainsFold,omitempty"` + + // "host" edge predicates. + HasHost *bool `json:"hasHost,omitempty"` + HasHostWith []*HostWhereInput `json:"hasHostWith,omitempty"` + + // "task" edge predicates. + HasTask *bool `json:"hasTask,omitempty"` + HasTaskWith []*TaskWhereInput `json:"hasTaskWith,omitempty"` } // AddPredicates adds custom predicates to the where input to be used during the filtering phase. @@ -1418,6 +1468,54 @@ func (i *ProcessWhereInput) P() (predicate.Process, error) { if i.IDLTE != nil { predicates = append(predicates, process.IDLTE(*i.IDLTE)) } + if i.CreatedAt != nil { + predicates = append(predicates, process.CreatedAtEQ(*i.CreatedAt)) + } + if i.CreatedAtNEQ != nil { + predicates = append(predicates, process.CreatedAtNEQ(*i.CreatedAtNEQ)) + } + if len(i.CreatedAtIn) > 0 { + predicates = append(predicates, process.CreatedAtIn(i.CreatedAtIn...)) + } + if len(i.CreatedAtNotIn) > 0 { + predicates = append(predicates, process.CreatedAtNotIn(i.CreatedAtNotIn...)) + } + if i.CreatedAtGT != nil { + predicates = append(predicates, process.CreatedAtGT(*i.CreatedAtGT)) + } + if i.CreatedAtGTE != nil { + predicates = append(predicates, process.CreatedAtGTE(*i.CreatedAtGTE)) + } + if i.CreatedAtLT != nil { + predicates = append(predicates, process.CreatedAtLT(*i.CreatedAtLT)) + } + if i.CreatedAtLTE != nil { + predicates = append(predicates, process.CreatedAtLTE(*i.CreatedAtLTE)) + } + if i.LastModifiedAt != nil { + predicates = append(predicates, process.LastModifiedAtEQ(*i.LastModifiedAt)) + } + if i.LastModifiedAtNEQ != nil { + predicates = append(predicates, process.LastModifiedAtNEQ(*i.LastModifiedAtNEQ)) + } + if len(i.LastModifiedAtIn) > 0 { + predicates = append(predicates, process.LastModifiedAtIn(i.LastModifiedAtIn...)) + } + if len(i.LastModifiedAtNotIn) > 0 { + predicates = append(predicates, process.LastModifiedAtNotIn(i.LastModifiedAtNotIn...)) + } + if i.LastModifiedAtGT != nil { + predicates = append(predicates, process.LastModifiedAtGT(*i.LastModifiedAtGT)) + } + if i.LastModifiedAtGTE != nil { + predicates = append(predicates, process.LastModifiedAtGTE(*i.LastModifiedAtGTE)) + } + if i.LastModifiedAtLT != nil { + predicates = append(predicates, process.LastModifiedAtLT(*i.LastModifiedAtLT)) + } + if i.LastModifiedAtLTE != nil { + predicates = append(predicates, process.LastModifiedAtLTE(*i.LastModifiedAtLTE)) + } if i.Pid != nil { predicates = append(predicates, process.PidEQ(*i.Pid)) } @@ -1521,6 +1619,42 @@ func (i *ProcessWhereInput) P() (predicate.Process, error) { predicates = append(predicates, process.PrincipalContainsFold(*i.PrincipalContainsFold)) } + if i.HasHost != nil { + p := process.HasHost() + if !*i.HasHost { + p = process.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasHostWith) > 0 { + with := make([]predicate.Host, 0, len(i.HasHostWith)) + for _, w := range i.HasHostWith { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'HasHostWith'", err) + } + with = append(with, p) + } + predicates = append(predicates, process.HasHostWith(with...)) + } + if i.HasTask != nil { + p := process.HasTask() + if !*i.HasTask { + p = process.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasTaskWith) > 0 { + with := make([]predicate.Task, 0, len(i.HasTaskWith)) + for _, w := range i.HasTaskWith { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'HasTaskWith'", err) + } + with = append(with, p) + } + predicates = append(predicates, process.HasTaskWith(with...)) + } switch len(predicates) { case 0: return nil, ErrEmptyProcessWhereInput diff --git a/tavern/internal/ent/host.go b/tavern/internal/ent/host.go index 0c298d5cc..43d2da5b5 100644 --- a/tavern/internal/ent/host.go +++ b/tavern/internal/ent/host.go @@ -39,14 +39,17 @@ type HostEdges struct { Tags []*Tag `json:"tags,omitempty"` // Beacons that are present on this host system. Beacons []*Beacon `json:"beacons,omitempty"` + // Processes reported as running on this host system. + Processes []*Process `json:"processes,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [3]bool // totalCount holds the count of the edges above. - totalCount [2]map[string]int + totalCount [3]map[string]int - namedTags map[string][]*Tag - namedBeacons map[string][]*Beacon + namedTags map[string][]*Tag + namedBeacons map[string][]*Beacon + namedProcesses map[string][]*Process } // TagsOrErr returns the Tags value or an error if the edge @@ -67,6 +70,15 @@ func (e HostEdges) BeaconsOrErr() ([]*Beacon, error) { return nil, &NotLoadedError{edge: "beacons"} } +// ProcessesOrErr returns the Processes value or an error if the edge +// was not loaded in eager-loading. +func (e HostEdges) ProcessesOrErr() ([]*Process, error) { + if e.loadedTypes[2] { + return e.Processes, nil + } + return nil, &NotLoadedError{edge: "processes"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Host) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) @@ -152,6 +164,11 @@ func (h *Host) QueryBeacons() *BeaconQuery { return NewHostClient(h.config).QueryBeacons(h) } +// QueryProcesses queries the "processes" edge of the Host entity. +func (h *Host) QueryProcesses() *ProcessQuery { + return NewHostClient(h.config).QueryProcesses(h) +} + // Update returns a builder for updating this Host. // Note that you need to call Host.Unwrap() before calling this method if this Host // was returned from a transaction, and the transaction was committed or rolled back. @@ -241,5 +258,29 @@ func (h *Host) appendNamedBeacons(name string, edges ...*Beacon) { } } +// NamedProcesses returns the Processes named value or an error if the edge was not +// loaded in eager-loading with this name. +func (h *Host) NamedProcesses(name string) ([]*Process, error) { + if h.Edges.namedProcesses == nil { + return nil, &NotLoadedError{edge: name} + } + nodes, ok := h.Edges.namedProcesses[name] + if !ok { + return nil, &NotLoadedError{edge: name} + } + return nodes, nil +} + +func (h *Host) appendNamedProcesses(name string, edges ...*Process) { + if h.Edges.namedProcesses == nil { + h.Edges.namedProcesses = make(map[string][]*Process) + } + if len(edges) == 0 { + h.Edges.namedProcesses[name] = []*Process{} + } else { + h.Edges.namedProcesses[name] = append(h.Edges.namedProcesses[name], edges...) + } +} + // Hosts is a parsable slice of Host. type Hosts []*Host diff --git a/tavern/internal/ent/host/host.go b/tavern/internal/ent/host/host.go index b5633e975..672f73c8a 100644 --- a/tavern/internal/ent/host/host.go +++ b/tavern/internal/ent/host/host.go @@ -30,6 +30,8 @@ const ( EdgeTags = "tags" // EdgeBeacons holds the string denoting the beacons edge name in mutations. EdgeBeacons = "beacons" + // EdgeProcesses holds the string denoting the processes edge name in mutations. + EdgeProcesses = "processes" // Table holds the table name of the host in the database. Table = "hosts" // TagsTable is the table that holds the tags relation/edge. The primary key declared below. @@ -44,6 +46,13 @@ const ( BeaconsInverseTable = "beacons" // BeaconsColumn is the table column denoting the beacons relation/edge. BeaconsColumn = "beacon_host" + // ProcessesTable is the table that holds the processes relation/edge. + ProcessesTable = "processes" + // ProcessesInverseTable is the table name for the Process entity. + // It exists in this package in order to avoid circular dependency with the "process" package. + ProcessesInverseTable = "processes" + // ProcessesColumn is the table column denoting the processes relation/edge. + ProcessesColumn = "host_processes" ) // Columns holds all SQL columns for host fields. @@ -168,6 +177,20 @@ func ByBeacons(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { sqlgraph.OrderByNeighborTerms(s, newBeaconsStep(), append([]sql.OrderTerm{term}, terms...)...) } } + +// ByProcessesCount orders the results by processes count. +func ByProcessesCount(opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborsCount(s, newProcessesStep(), opts...) + } +} + +// ByProcesses orders the results by processes terms. +func ByProcesses(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newProcessesStep(), append([]sql.OrderTerm{term}, terms...)...) + } +} func newTagsStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -182,6 +205,13 @@ func newBeaconsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, true, BeaconsTable, BeaconsColumn), ) } +func newProcessesStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ProcessesInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ProcessesTable, ProcessesColumn), + ) +} // MarshalGQL implements graphql.Marshaler interface. func (e Platform) MarshalGQL(w io.Writer) { diff --git a/tavern/internal/ent/host/where.go b/tavern/internal/ent/host/where.go index dd7ce66a4..5d84635f1 100644 --- a/tavern/internal/ent/host/where.go +++ b/tavern/internal/ent/host/where.go @@ -406,6 +406,29 @@ func HasBeaconsWith(preds ...predicate.Beacon) predicate.Host { }) } +// HasProcesses applies the HasEdge predicate on the "processes" edge. +func HasProcesses() predicate.Host { + return predicate.Host(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ProcessesTable, ProcessesColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasProcessesWith applies the HasEdge predicate on the "processes" edge with a given conditions (other predicates). +func HasProcessesWith(preds ...predicate.Process) predicate.Host { + return predicate.Host(func(s *sql.Selector) { + step := newProcessesStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Host) predicate.Host { return predicate.Host(sql.AndPredicates(predicates...)) diff --git a/tavern/internal/ent/host_create.go b/tavern/internal/ent/host_create.go index 53264f5e7..e0654973c 100644 --- a/tavern/internal/ent/host_create.go +++ b/tavern/internal/ent/host_create.go @@ -13,6 +13,7 @@ import ( "entgo.io/ent/schema/field" "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/host" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/tag" ) @@ -116,6 +117,21 @@ func (hc *HostCreate) AddBeacons(b ...*Beacon) *HostCreate { return hc.AddBeaconIDs(ids...) } +// AddProcessIDs adds the "processes" edge to the Process entity by IDs. +func (hc *HostCreate) AddProcessIDs(ids ...int) *HostCreate { + hc.mutation.AddProcessIDs(ids...) + return hc +} + +// AddProcesses adds the "processes" edges to the Process entity. +func (hc *HostCreate) AddProcesses(p ...*Process) *HostCreate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return hc.AddProcessIDs(ids...) +} + // Mutation returns the HostMutation object of the builder. func (hc *HostCreate) Mutation() *HostMutation { return hc.mutation @@ -259,6 +275,22 @@ func (hc *HostCreate) createSpec() (*Host, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := hc.mutation.ProcessesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/tavern/internal/ent/host_query.go b/tavern/internal/ent/host_query.go index 553fc21c2..a2f0077b4 100644 --- a/tavern/internal/ent/host_query.go +++ b/tavern/internal/ent/host_query.go @@ -14,22 +14,25 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/tag" ) // HostQuery is the builder for querying Host entities. type HostQuery struct { config - ctx *QueryContext - order []host.OrderOption - inters []Interceptor - predicates []predicate.Host - withTags *TagQuery - withBeacons *BeaconQuery - modifiers []func(*sql.Selector) - loadTotal []func(context.Context, []*Host) error - withNamedTags map[string]*TagQuery - withNamedBeacons map[string]*BeaconQuery + ctx *QueryContext + order []host.OrderOption + inters []Interceptor + predicates []predicate.Host + withTags *TagQuery + withBeacons *BeaconQuery + withProcesses *ProcessQuery + modifiers []func(*sql.Selector) + loadTotal []func(context.Context, []*Host) error + withNamedTags map[string]*TagQuery + withNamedBeacons map[string]*BeaconQuery + withNamedProcesses map[string]*ProcessQuery // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -110,6 +113,28 @@ func (hq *HostQuery) QueryBeacons() *BeaconQuery { return query } +// QueryProcesses chains the current query on the "processes" edge. +func (hq *HostQuery) QueryProcesses() *ProcessQuery { + query := (&ProcessClient{config: hq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := hq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := hq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(host.Table, host.FieldID, selector), + sqlgraph.To(process.Table, process.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, host.ProcessesTable, host.ProcessesColumn), + ) + fromU = sqlgraph.SetNeighbors(hq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Host entity from the query. // Returns a *NotFoundError when no Host was found. func (hq *HostQuery) First(ctx context.Context) (*Host, error) { @@ -297,13 +322,14 @@ func (hq *HostQuery) Clone() *HostQuery { return nil } return &HostQuery{ - config: hq.config, - ctx: hq.ctx.Clone(), - order: append([]host.OrderOption{}, hq.order...), - inters: append([]Interceptor{}, hq.inters...), - predicates: append([]predicate.Host{}, hq.predicates...), - withTags: hq.withTags.Clone(), - withBeacons: hq.withBeacons.Clone(), + config: hq.config, + ctx: hq.ctx.Clone(), + order: append([]host.OrderOption{}, hq.order...), + inters: append([]Interceptor{}, hq.inters...), + predicates: append([]predicate.Host{}, hq.predicates...), + withTags: hq.withTags.Clone(), + withBeacons: hq.withBeacons.Clone(), + withProcesses: hq.withProcesses.Clone(), // clone intermediate query. sql: hq.sql.Clone(), path: hq.path, @@ -332,6 +358,17 @@ func (hq *HostQuery) WithBeacons(opts ...func(*BeaconQuery)) *HostQuery { return hq } +// WithProcesses tells the query-builder to eager-load the nodes that are connected to +// the "processes" edge. The optional arguments are used to configure the query builder of the edge. +func (hq *HostQuery) WithProcesses(opts ...func(*ProcessQuery)) *HostQuery { + query := (&ProcessClient{config: hq.config}).Query() + for _, opt := range opts { + opt(query) + } + hq.withProcesses = query + return hq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -410,9 +447,10 @@ func (hq *HostQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Host, e var ( nodes = []*Host{} _spec = hq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [3]bool{ hq.withTags != nil, hq.withBeacons != nil, + hq.withProcesses != nil, } ) _spec.ScanValues = func(columns []string) ([]any, error) { @@ -450,6 +488,13 @@ func (hq *HostQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Host, e return nil, err } } + if query := hq.withProcesses; query != nil { + if err := hq.loadProcesses(ctx, query, nodes, + func(n *Host) { n.Edges.Processes = []*Process{} }, + func(n *Host, e *Process) { n.Edges.Processes = append(n.Edges.Processes, e) }); err != nil { + return nil, err + } + } for name, query := range hq.withNamedTags { if err := hq.loadTags(ctx, query, nodes, func(n *Host) { n.appendNamedTags(name) }, @@ -464,6 +509,13 @@ func (hq *HostQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Host, e return nil, err } } + for name, query := range hq.withNamedProcesses { + if err := hq.loadProcesses(ctx, query, nodes, + func(n *Host) { n.appendNamedProcesses(name) }, + func(n *Host, e *Process) { n.appendNamedProcesses(name, e) }); err != nil { + return nil, err + } + } for i := range hq.loadTotal { if err := hq.loadTotal[i](ctx, nodes); err != nil { return nil, err @@ -564,6 +616,37 @@ func (hq *HostQuery) loadBeacons(ctx context.Context, query *BeaconQuery, nodes } return nil } +func (hq *HostQuery) loadProcesses(ctx context.Context, query *ProcessQuery, nodes []*Host, init func(*Host), assign func(*Host, *Process)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Host) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + query.withFKs = true + query.Where(predicate.Process(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(host.ProcessesColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.host_processes + if fk == nil { + return fmt.Errorf(`foreign-key "host_processes" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "host_processes" returned %v for node %v`, *fk, n.ID) + } + assign(node, n) + } + return nil +} func (hq *HostQuery) sqlCount(ctx context.Context) (int, error) { _spec := hq.querySpec() @@ -677,6 +760,20 @@ func (hq *HostQuery) WithNamedBeacons(name string, opts ...func(*BeaconQuery)) * return hq } +// WithNamedProcesses tells the query-builder to eager-load the nodes that are connected to the "processes" +// edge with the given name. The optional arguments are used to configure the query builder of the edge. +func (hq *HostQuery) WithNamedProcesses(name string, opts ...func(*ProcessQuery)) *HostQuery { + query := (&ProcessClient{config: hq.config}).Query() + for _, opt := range opts { + opt(query) + } + if hq.withNamedProcesses == nil { + hq.withNamedProcesses = make(map[string]*ProcessQuery) + } + hq.withNamedProcesses[name] = query + return hq +} + // HostGroupBy is the group-by builder for Host entities. type HostGroupBy struct { selector diff --git a/tavern/internal/ent/host_update.go b/tavern/internal/ent/host_update.go index c205e3064..73db365e0 100644 --- a/tavern/internal/ent/host_update.go +++ b/tavern/internal/ent/host_update.go @@ -14,6 +14,7 @@ import ( "realm.pub/tavern/internal/ent/beacon" "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/predicate" + "realm.pub/tavern/internal/ent/process" "realm.pub/tavern/internal/ent/tag" ) @@ -140,6 +141,21 @@ func (hu *HostUpdate) AddBeacons(b ...*Beacon) *HostUpdate { return hu.AddBeaconIDs(ids...) } +// AddProcessIDs adds the "processes" edge to the Process entity by IDs. +func (hu *HostUpdate) AddProcessIDs(ids ...int) *HostUpdate { + hu.mutation.AddProcessIDs(ids...) + return hu +} + +// AddProcesses adds the "processes" edges to the Process entity. +func (hu *HostUpdate) AddProcesses(p ...*Process) *HostUpdate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return hu.AddProcessIDs(ids...) +} + // Mutation returns the HostMutation object of the builder. func (hu *HostUpdate) Mutation() *HostMutation { return hu.mutation @@ -187,6 +203,27 @@ func (hu *HostUpdate) RemoveBeacons(b ...*Beacon) *HostUpdate { return hu.RemoveBeaconIDs(ids...) } +// ClearProcesses clears all "processes" edges to the Process entity. +func (hu *HostUpdate) ClearProcesses() *HostUpdate { + hu.mutation.ClearProcesses() + return hu +} + +// RemoveProcessIDs removes the "processes" edge to Process entities by IDs. +func (hu *HostUpdate) RemoveProcessIDs(ids ...int) *HostUpdate { + hu.mutation.RemoveProcessIDs(ids...) + return hu +} + +// RemoveProcesses removes "processes" edges to Process entities. +func (hu *HostUpdate) RemoveProcesses(p ...*Process) *HostUpdate { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return hu.RemoveProcessIDs(ids...) +} + // Save executes the query and returns the number of nodes affected by the update operation. func (hu *HostUpdate) Save(ctx context.Context) (int, error) { return withHooks(ctx, hu.sqlSave, hu.mutation, hu.hooks) @@ -360,6 +397,51 @@ func (hu *HostUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if hu.mutation.ProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := hu.mutation.RemovedProcessesIDs(); len(nodes) > 0 && !hu.mutation.ProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := hu.mutation.ProcessesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, hu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{host.Label} @@ -490,6 +572,21 @@ func (huo *HostUpdateOne) AddBeacons(b ...*Beacon) *HostUpdateOne { return huo.AddBeaconIDs(ids...) } +// AddProcessIDs adds the "processes" edge to the Process entity by IDs. +func (huo *HostUpdateOne) AddProcessIDs(ids ...int) *HostUpdateOne { + huo.mutation.AddProcessIDs(ids...) + return huo +} + +// AddProcesses adds the "processes" edges to the Process entity. +func (huo *HostUpdateOne) AddProcesses(p ...*Process) *HostUpdateOne { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return huo.AddProcessIDs(ids...) +} + // Mutation returns the HostMutation object of the builder. func (huo *HostUpdateOne) Mutation() *HostMutation { return huo.mutation @@ -537,6 +634,27 @@ func (huo *HostUpdateOne) RemoveBeacons(b ...*Beacon) *HostUpdateOne { return huo.RemoveBeaconIDs(ids...) } +// ClearProcesses clears all "processes" edges to the Process entity. +func (huo *HostUpdateOne) ClearProcesses() *HostUpdateOne { + huo.mutation.ClearProcesses() + return huo +} + +// RemoveProcessIDs removes the "processes" edge to Process entities by IDs. +func (huo *HostUpdateOne) RemoveProcessIDs(ids ...int) *HostUpdateOne { + huo.mutation.RemoveProcessIDs(ids...) + return huo +} + +// RemoveProcesses removes "processes" edges to Process entities. +func (huo *HostUpdateOne) RemoveProcesses(p ...*Process) *HostUpdateOne { + ids := make([]int, len(p)) + for i := range p { + ids[i] = p[i].ID + } + return huo.RemoveProcessIDs(ids...) +} + // Where appends a list predicates to the HostUpdate builder. func (huo *HostUpdateOne) Where(ps ...predicate.Host) *HostUpdateOne { huo.mutation.Where(ps...) @@ -740,6 +858,51 @@ func (huo *HostUpdateOne) sqlSave(ctx context.Context) (_node *Host, err error) } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if huo.mutation.ProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := huo.mutation.RemovedProcessesIDs(); len(nodes) > 0 && !huo.mutation.ProcessesCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := huo.mutation.ProcessesIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: host.ProcessesTable, + Columns: []string{host.ProcessesColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &Host{config: huo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/tavern/internal/ent/migrate/schema.go b/tavern/internal/ent/migrate/schema.go index 070589e19..4cb1fff0c 100644 --- a/tavern/internal/ent/migrate/schema.go +++ b/tavern/internal/ent/migrate/schema.go @@ -67,10 +67,14 @@ var ( // ProcessesColumns holds the columns for the "processes" table. ProcessesColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "last_modified_at", Type: field.TypeTime}, {Name: "pid", Type: field.TypeUint64}, {Name: "name", Type: field.TypeString}, {Name: "principal", Type: field.TypeString}, - {Name: "task_reported_processes", Type: field.TypeInt, Nullable: true}, + {Name: "host_processes", Type: field.TypeInt, Nullable: true}, + {Name: "process_host", Type: field.TypeInt}, + {Name: "task_reported_processes", Type: field.TypeInt}, } // ProcessesTable holds the schema information for the "processes" table. ProcessesTable = &schema.Table{ @@ -78,11 +82,23 @@ var ( Columns: ProcessesColumns, PrimaryKey: []*schema.Column{ProcessesColumns[0]}, ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "processes_hosts_processes", + Columns: []*schema.Column{ProcessesColumns[6]}, + RefColumns: []*schema.Column{HostsColumns[0]}, + OnDelete: schema.SetNull, + }, + { + Symbol: "processes_hosts_host", + Columns: []*schema.Column{ProcessesColumns[7]}, + RefColumns: []*schema.Column{HostsColumns[0]}, + OnDelete: schema.NoAction, + }, { Symbol: "processes_tasks_reported_processes", - Columns: []*schema.Column{ProcessesColumns[4]}, + Columns: []*schema.Column{ProcessesColumns[8]}, RefColumns: []*schema.Column{TasksColumns[0]}, - OnDelete: schema.SetNull, + OnDelete: schema.NoAction, }, }, } @@ -270,7 +286,9 @@ var ( func init() { BeaconsTable.ForeignKeys[0].RefTable = HostsTable - ProcessesTable.ForeignKeys[0].RefTable = TasksTable + ProcessesTable.ForeignKeys[0].RefTable = HostsTable + ProcessesTable.ForeignKeys[1].RefTable = HostsTable + ProcessesTable.ForeignKeys[2].RefTable = TasksTable QuestsTable.ForeignKeys[0].RefTable = TomesTable QuestsTable.ForeignKeys[1].RefTable = FilesTable QuestsTable.ForeignKeys[2].RefTable = UsersTable diff --git a/tavern/internal/ent/mutation.go b/tavern/internal/ent/mutation.go index 71f3cb09e..14059f6b4 100644 --- a/tavern/internal/ent/mutation.go +++ b/tavern/internal/ent/mutation.go @@ -1635,24 +1635,27 @@ func (m *FileMutation) ResetEdge(name string) error { // HostMutation represents an operation that mutates the Host nodes in the graph. type HostMutation struct { config - op Op - typ string - id *int - identifier *string - name *string - primary_ip *string - platform *host.Platform - last_seen_at *time.Time - clearedFields map[string]struct{} - tags map[int]struct{} - removedtags map[int]struct{} - clearedtags bool - beacons map[int]struct{} - removedbeacons map[int]struct{} - clearedbeacons bool - done bool - oldValue func(context.Context) (*Host, error) - predicates []predicate.Host + op Op + typ string + id *int + identifier *string + name *string + primary_ip *string + platform *host.Platform + last_seen_at *time.Time + clearedFields map[string]struct{} + tags map[int]struct{} + removedtags map[int]struct{} + clearedtags bool + beacons map[int]struct{} + removedbeacons map[int]struct{} + clearedbeacons bool + processes map[int]struct{} + removedprocesses map[int]struct{} + clearedprocesses bool + done bool + oldValue func(context.Context) (*Host, error) + predicates []predicate.Host } var _ ent.Mutation = (*HostMutation)(nil) @@ -2080,6 +2083,60 @@ func (m *HostMutation) ResetBeacons() { m.removedbeacons = nil } +// AddProcessIDs adds the "processes" edge to the Process entity by ids. +func (m *HostMutation) AddProcessIDs(ids ...int) { + if m.processes == nil { + m.processes = make(map[int]struct{}) + } + for i := range ids { + m.processes[ids[i]] = struct{}{} + } +} + +// ClearProcesses clears the "processes" edge to the Process entity. +func (m *HostMutation) ClearProcesses() { + m.clearedprocesses = true +} + +// ProcessesCleared reports if the "processes" edge to the Process entity was cleared. +func (m *HostMutation) ProcessesCleared() bool { + return m.clearedprocesses +} + +// RemoveProcessIDs removes the "processes" edge to the Process entity by IDs. +func (m *HostMutation) RemoveProcessIDs(ids ...int) { + if m.removedprocesses == nil { + m.removedprocesses = make(map[int]struct{}) + } + for i := range ids { + delete(m.processes, ids[i]) + m.removedprocesses[ids[i]] = struct{}{} + } +} + +// RemovedProcesses returns the removed IDs of the "processes" edge to the Process entity. +func (m *HostMutation) RemovedProcessesIDs() (ids []int) { + for id := range m.removedprocesses { + ids = append(ids, id) + } + return +} + +// ProcessesIDs returns the "processes" edge IDs in the mutation. +func (m *HostMutation) ProcessesIDs() (ids []int) { + for id := range m.processes { + ids = append(ids, id) + } + return +} + +// ResetProcesses resets all changes to the "processes" edge. +func (m *HostMutation) ResetProcesses() { + m.processes = nil + m.clearedprocesses = false + m.removedprocesses = nil +} + // Where appends a list predicates to the HostMutation builder. func (m *HostMutation) Where(ps ...predicate.Host) { m.predicates = append(m.predicates, ps...) @@ -2302,13 +2359,16 @@ func (m *HostMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *HostMutation) AddedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.tags != nil { edges = append(edges, host.EdgeTags) } if m.beacons != nil { edges = append(edges, host.EdgeBeacons) } + if m.processes != nil { + edges = append(edges, host.EdgeProcesses) + } return edges } @@ -2328,19 +2388,28 @@ func (m *HostMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case host.EdgeProcesses: + ids := make([]ent.Value, 0, len(m.processes)) + for id := range m.processes { + ids = append(ids, id) + } + return ids } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *HostMutation) RemovedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.removedtags != nil { edges = append(edges, host.EdgeTags) } if m.removedbeacons != nil { edges = append(edges, host.EdgeBeacons) } + if m.removedprocesses != nil { + edges = append(edges, host.EdgeProcesses) + } return edges } @@ -2360,19 +2429,28 @@ func (m *HostMutation) RemovedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case host.EdgeProcesses: + ids := make([]ent.Value, 0, len(m.removedprocesses)) + for id := range m.removedprocesses { + ids = append(ids, id) + } + return ids } return nil } // ClearedEdges returns all edge names that were cleared in this mutation. func (m *HostMutation) ClearedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 3) if m.clearedtags { edges = append(edges, host.EdgeTags) } if m.clearedbeacons { edges = append(edges, host.EdgeBeacons) } + if m.clearedprocesses { + edges = append(edges, host.EdgeProcesses) + } return edges } @@ -2384,6 +2462,8 @@ func (m *HostMutation) EdgeCleared(name string) bool { return m.clearedtags case host.EdgeBeacons: return m.clearedbeacons + case host.EdgeProcesses: + return m.clearedprocesses } return false } @@ -2406,6 +2486,9 @@ func (m *HostMutation) ResetEdge(name string) error { case host.EdgeBeacons: m.ResetBeacons() return nil + case host.EdgeProcesses: + m.ResetProcesses() + return nil } return fmt.Errorf("unknown Host edge %s", name) } @@ -2413,17 +2496,23 @@ func (m *HostMutation) ResetEdge(name string) error { // ProcessMutation represents an operation that mutates the Process nodes in the graph. type ProcessMutation struct { config - op Op - typ string - id *int - pid *uint64 - addpid *int64 - name *string - principal *string - clearedFields map[string]struct{} - done bool - oldValue func(context.Context) (*Process, error) - predicates []predicate.Process + op Op + typ string + id *int + created_at *time.Time + last_modified_at *time.Time + pid *uint64 + addpid *int64 + name *string + principal *string + clearedFields map[string]struct{} + host *int + clearedhost bool + task *int + clearedtask bool + done bool + oldValue func(context.Context) (*Process, error) + predicates []predicate.Process } var _ ent.Mutation = (*ProcessMutation)(nil) @@ -2524,6 +2613,78 @@ func (m *ProcessMutation) IDs(ctx context.Context) ([]int, error) { } } +// SetCreatedAt sets the "created_at" field. +func (m *ProcessMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *ProcessMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Process entity. +// If the Process object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProcessMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *ProcessMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetLastModifiedAt sets the "last_modified_at" field. +func (m *ProcessMutation) SetLastModifiedAt(t time.Time) { + m.last_modified_at = &t +} + +// LastModifiedAt returns the value of the "last_modified_at" field in the mutation. +func (m *ProcessMutation) LastModifiedAt() (r time.Time, exists bool) { + v := m.last_modified_at + if v == nil { + return + } + return *v, true +} + +// OldLastModifiedAt returns the old "last_modified_at" field's value of the Process entity. +// If the Process object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProcessMutation) OldLastModifiedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLastModifiedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLastModifiedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLastModifiedAt: %w", err) + } + return oldValue.LastModifiedAt, nil +} + +// ResetLastModifiedAt resets all changes to the "last_modified_at" field. +func (m *ProcessMutation) ResetLastModifiedAt() { + m.last_modified_at = nil +} + // SetPid sets the "pid" field. func (m *ProcessMutation) SetPid(u uint64) { m.pid = &u @@ -2652,6 +2813,84 @@ func (m *ProcessMutation) ResetPrincipal() { m.principal = nil } +// SetHostID sets the "host" edge to the Host entity by id. +func (m *ProcessMutation) SetHostID(id int) { + m.host = &id +} + +// ClearHost clears the "host" edge to the Host entity. +func (m *ProcessMutation) ClearHost() { + m.clearedhost = true +} + +// HostCleared reports if the "host" edge to the Host entity was cleared. +func (m *ProcessMutation) HostCleared() bool { + return m.clearedhost +} + +// HostID returns the "host" edge ID in the mutation. +func (m *ProcessMutation) HostID() (id int, exists bool) { + if m.host != nil { + return *m.host, true + } + return +} + +// HostIDs returns the "host" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// HostID instead. It exists only for internal usage by the builders. +func (m *ProcessMutation) HostIDs() (ids []int) { + if id := m.host; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetHost resets all changes to the "host" edge. +func (m *ProcessMutation) ResetHost() { + m.host = nil + m.clearedhost = false +} + +// SetTaskID sets the "task" edge to the Task entity by id. +func (m *ProcessMutation) SetTaskID(id int) { + m.task = &id +} + +// ClearTask clears the "task" edge to the Task entity. +func (m *ProcessMutation) ClearTask() { + m.clearedtask = true +} + +// TaskCleared reports if the "task" edge to the Task entity was cleared. +func (m *ProcessMutation) TaskCleared() bool { + return m.clearedtask +} + +// TaskID returns the "task" edge ID in the mutation. +func (m *ProcessMutation) TaskID() (id int, exists bool) { + if m.task != nil { + return *m.task, true + } + return +} + +// TaskIDs returns the "task" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// TaskID instead. It exists only for internal usage by the builders. +func (m *ProcessMutation) TaskIDs() (ids []int) { + if id := m.task; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetTask resets all changes to the "task" edge. +func (m *ProcessMutation) ResetTask() { + m.task = nil + m.clearedtask = false +} + // Where appends a list predicates to the ProcessMutation builder. func (m *ProcessMutation) Where(ps ...predicate.Process) { m.predicates = append(m.predicates, ps...) @@ -2686,7 +2925,13 @@ func (m *ProcessMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *ProcessMutation) Fields() []string { - fields := make([]string, 0, 3) + fields := make([]string, 0, 5) + if m.created_at != nil { + fields = append(fields, process.FieldCreatedAt) + } + if m.last_modified_at != nil { + fields = append(fields, process.FieldLastModifiedAt) + } if m.pid != nil { fields = append(fields, process.FieldPid) } @@ -2704,6 +2949,10 @@ func (m *ProcessMutation) Fields() []string { // schema. func (m *ProcessMutation) Field(name string) (ent.Value, bool) { switch name { + case process.FieldCreatedAt: + return m.CreatedAt() + case process.FieldLastModifiedAt: + return m.LastModifiedAt() case process.FieldPid: return m.Pid() case process.FieldName: @@ -2719,6 +2968,10 @@ func (m *ProcessMutation) Field(name string) (ent.Value, bool) { // database failed. func (m *ProcessMutation) OldField(ctx context.Context, name string) (ent.Value, error) { switch name { + case process.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case process.FieldLastModifiedAt: + return m.OldLastModifiedAt(ctx) case process.FieldPid: return m.OldPid(ctx) case process.FieldName: @@ -2734,6 +2987,20 @@ func (m *ProcessMutation) OldField(ctx context.Context, name string) (ent.Value, // type. func (m *ProcessMutation) SetField(name string, value ent.Value) error { switch name { + case process.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case process.FieldLastModifiedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLastModifiedAt(v) + return nil case process.FieldPid: v, ok := value.(uint64) if !ok { @@ -2819,6 +3086,12 @@ func (m *ProcessMutation) ClearField(name string) error { // It returns an error if the field is not defined in the schema. func (m *ProcessMutation) ResetField(name string) error { switch name { + case process.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case process.FieldLastModifiedAt: + m.ResetLastModifiedAt() + return nil case process.FieldPid: m.ResetPid() return nil @@ -2834,19 +3107,35 @@ func (m *ProcessMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *ProcessMutation) AddedEdges() []string { - edges := make([]string, 0, 0) + edges := make([]string, 0, 2) + if m.host != nil { + edges = append(edges, process.EdgeHost) + } + if m.task != nil { + edges = append(edges, process.EdgeTask) + } return edges } // AddedIDs returns all IDs (to other nodes) that were added for the given edge // name in this mutation. func (m *ProcessMutation) AddedIDs(name string) []ent.Value { + switch name { + case process.EdgeHost: + if id := m.host; id != nil { + return []ent.Value{*id} + } + case process.EdgeTask: + if id := m.task; id != nil { + return []ent.Value{*id} + } + } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *ProcessMutation) RemovedEdges() []string { - edges := make([]string, 0, 0) + edges := make([]string, 0, 2) return edges } @@ -2858,25 +3147,53 @@ func (m *ProcessMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *ProcessMutation) ClearedEdges() []string { - edges := make([]string, 0, 0) + edges := make([]string, 0, 2) + if m.clearedhost { + edges = append(edges, process.EdgeHost) + } + if m.clearedtask { + edges = append(edges, process.EdgeTask) + } return edges } // EdgeCleared returns a boolean which indicates if the edge with the given name // was cleared in this mutation. func (m *ProcessMutation) EdgeCleared(name string) bool { + switch name { + case process.EdgeHost: + return m.clearedhost + case process.EdgeTask: + return m.clearedtask + } return false } // ClearEdge clears the value of the edge with the given name. It returns an error // if that edge is not defined in the schema. func (m *ProcessMutation) ClearEdge(name string) error { + switch name { + case process.EdgeHost: + m.ClearHost() + return nil + case process.EdgeTask: + m.ClearTask() + return nil + } return fmt.Errorf("unknown Process unique edge %s", name) } // ResetEdge resets all changes to the edge with the given name in this mutation. // It returns an error if the edge is not defined in the schema. func (m *ProcessMutation) ResetEdge(name string) error { + switch name { + case process.EdgeHost: + m.ResetHost() + return nil + case process.EdgeTask: + m.ResetTask() + return nil + } return fmt.Errorf("unknown Process edge %s", name) } diff --git a/tavern/internal/ent/process.go b/tavern/internal/ent/process.go index 47707f078..54232e527 100644 --- a/tavern/internal/ent/process.go +++ b/tavern/internal/ent/process.go @@ -5,10 +5,13 @@ package ent import ( "fmt" "strings" + "time" "entgo.io/ent" "entgo.io/ent/dialect/sql" + "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/process" + "realm.pub/tavern/internal/ent/task" ) // Process is the model entity for the Process schema. @@ -16,16 +19,64 @@ type Process struct { config `json:"-"` // ID of the ent. ID int `json:"id,omitempty"` + // Timestamp of when this ent was created + CreatedAt time.Time `json:"created_at,omitempty"` + // Timestamp of when this ent was last updated + LastModifiedAt time.Time `json:"last_modified_at,omitempty"` // ID of the process. Pid uint64 `json:"pid,omitempty"` // The name of the process. Name string `json:"name,omitempty"` // The user the process is running as. - Principal string `json:"principal,omitempty"` + Principal string `json:"principal,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the ProcessQuery when eager-loading is set. + Edges ProcessEdges `json:"edges"` + host_processes *int + process_host *int task_reported_processes *int selectValues sql.SelectValues } +// ProcessEdges holds the relations/edges for other nodes in the graph. +type ProcessEdges struct { + // Host the process was reported on. + Host *Host `json:"host,omitempty"` + // Task that reported this process. + Task *Task `json:"task,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool + // totalCount holds the count of the edges above. + totalCount [2]map[string]int +} + +// HostOrErr returns the Host value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e ProcessEdges) HostOrErr() (*Host, error) { + if e.loadedTypes[0] { + if e.Host == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: host.Label} + } + return e.Host, nil + } + return nil, &NotLoadedError{edge: "host"} +} + +// TaskOrErr returns the Task value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e ProcessEdges) TaskOrErr() (*Task, error) { + if e.loadedTypes[1] { + if e.Task == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: task.Label} + } + return e.Task, nil + } + return nil, &NotLoadedError{edge: "task"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Process) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) @@ -35,7 +86,13 @@ func (*Process) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullInt64) case process.FieldName, process.FieldPrincipal: values[i] = new(sql.NullString) - case process.ForeignKeys[0]: // task_reported_processes + case process.FieldCreatedAt, process.FieldLastModifiedAt: + values[i] = new(sql.NullTime) + case process.ForeignKeys[0]: // host_processes + values[i] = new(sql.NullInt64) + case process.ForeignKeys[1]: // process_host + values[i] = new(sql.NullInt64) + case process.ForeignKeys[2]: // task_reported_processes values[i] = new(sql.NullInt64) default: values[i] = new(sql.UnknownType) @@ -58,6 +115,18 @@ func (pr *Process) assignValues(columns []string, values []any) error { return fmt.Errorf("unexpected type %T for field id", value) } pr.ID = int(value.Int64) + case process.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + pr.CreatedAt = value.Time + } + case process.FieldLastModifiedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field last_modified_at", values[i]) + } else if value.Valid { + pr.LastModifiedAt = value.Time + } case process.FieldPid: if value, ok := values[i].(*sql.NullInt64); !ok { return fmt.Errorf("unexpected type %T for field pid", values[i]) @@ -77,6 +146,20 @@ func (pr *Process) assignValues(columns []string, values []any) error { pr.Principal = value.String } case process.ForeignKeys[0]: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field host_processes", value) + } else if value.Valid { + pr.host_processes = new(int) + *pr.host_processes = int(value.Int64) + } + case process.ForeignKeys[1]: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field process_host", value) + } else if value.Valid { + pr.process_host = new(int) + *pr.process_host = int(value.Int64) + } + case process.ForeignKeys[2]: if value, ok := values[i].(*sql.NullInt64); !ok { return fmt.Errorf("unexpected type %T for edge-field task_reported_processes", value) } else if value.Valid { @@ -96,6 +179,16 @@ func (pr *Process) Value(name string) (ent.Value, error) { return pr.selectValues.Get(name) } +// QueryHost queries the "host" edge of the Process entity. +func (pr *Process) QueryHost() *HostQuery { + return NewProcessClient(pr.config).QueryHost(pr) +} + +// QueryTask queries the "task" edge of the Process entity. +func (pr *Process) QueryTask() *TaskQuery { + return NewProcessClient(pr.config).QueryTask(pr) +} + // Update returns a builder for updating this Process. // Note that you need to call Process.Unwrap() before calling this method if this Process // was returned from a transaction, and the transaction was committed or rolled back. @@ -119,6 +212,12 @@ func (pr *Process) String() string { var builder strings.Builder builder.WriteString("Process(") builder.WriteString(fmt.Sprintf("id=%v, ", pr.ID)) + builder.WriteString("created_at=") + builder.WriteString(pr.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("last_modified_at=") + builder.WriteString(pr.LastModifiedAt.Format(time.ANSIC)) + builder.WriteString(", ") builder.WriteString("pid=") builder.WriteString(fmt.Sprintf("%v", pr.Pid)) builder.WriteString(", ") diff --git a/tavern/internal/ent/process/process.go b/tavern/internal/ent/process/process.go index ce6747efe..59a30eb16 100644 --- a/tavern/internal/ent/process/process.go +++ b/tavern/internal/ent/process/process.go @@ -3,7 +3,10 @@ package process import ( + "time" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" ) const ( @@ -11,19 +14,43 @@ const ( Label = "process" // FieldID holds the string denoting the id field in the database. FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldLastModifiedAt holds the string denoting the last_modified_at field in the database. + FieldLastModifiedAt = "last_modified_at" // FieldPid holds the string denoting the pid field in the database. FieldPid = "pid" // FieldName holds the string denoting the name field in the database. FieldName = "name" // FieldPrincipal holds the string denoting the principal field in the database. FieldPrincipal = "principal" + // EdgeHost holds the string denoting the host edge name in mutations. + EdgeHost = "host" + // EdgeTask holds the string denoting the task edge name in mutations. + EdgeTask = "task" // Table holds the table name of the process in the database. Table = "processes" + // HostTable is the table that holds the host relation/edge. + HostTable = "processes" + // HostInverseTable is the table name for the Host entity. + // It exists in this package in order to avoid circular dependency with the "host" package. + HostInverseTable = "hosts" + // HostColumn is the table column denoting the host relation/edge. + HostColumn = "process_host" + // TaskTable is the table that holds the task relation/edge. + TaskTable = "processes" + // TaskInverseTable is the table name for the Task entity. + // It exists in this package in order to avoid circular dependency with the "task" package. + TaskInverseTable = "tasks" + // TaskColumn is the table column denoting the task relation/edge. + TaskColumn = "task_reported_processes" ) // Columns holds all SQL columns for process fields. var Columns = []string{ FieldID, + FieldCreatedAt, + FieldLastModifiedAt, FieldPid, FieldName, FieldPrincipal, @@ -32,6 +59,8 @@ var Columns = []string{ // ForeignKeys holds the SQL foreign-keys that are owned by the "processes" // table and are not defined as standalone fields in the schema. var ForeignKeys = []string{ + "host_processes", + "process_host", "task_reported_processes", } @@ -51,6 +80,12 @@ func ValidColumn(column string) bool { } var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultLastModifiedAt holds the default value on creation for the "last_modified_at" field. + DefaultLastModifiedAt func() time.Time + // UpdateDefaultLastModifiedAt holds the default value on update for the "last_modified_at" field. + UpdateDefaultLastModifiedAt func() time.Time // PrincipalValidator is a validator for the "principal" field. It is called by the builders before save. PrincipalValidator func(string) error ) @@ -63,6 +98,16 @@ func ByID(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldID, opts...).ToFunc() } +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByLastModifiedAt orders the results by the last_modified_at field. +func ByLastModifiedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLastModifiedAt, opts...).ToFunc() +} + // ByPid orders the results by the pid field. func ByPid(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldPid, opts...).ToFunc() @@ -77,3 +122,31 @@ func ByName(opts ...sql.OrderTermOption) OrderOption { func ByPrincipal(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldPrincipal, opts...).ToFunc() } + +// ByHostField orders the results by host field. +func ByHostField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newHostStep(), sql.OrderByField(field, opts...)) + } +} + +// ByTaskField orders the results by task field. +func ByTaskField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newTaskStep(), sql.OrderByField(field, opts...)) + } +} +func newHostStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(HostInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, HostTable, HostColumn), + ) +} +func newTaskStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TaskInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, TaskTable, TaskColumn), + ) +} diff --git a/tavern/internal/ent/process/where.go b/tavern/internal/ent/process/where.go index e6a3208f5..000f89446 100644 --- a/tavern/internal/ent/process/where.go +++ b/tavern/internal/ent/process/where.go @@ -3,7 +3,10 @@ package process import ( + "time" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" "realm.pub/tavern/internal/ent/predicate" ) @@ -52,6 +55,16 @@ func IDLTE(id int) predicate.Process { return predicate.Process(sql.FieldLTE(FieldID, id)) } +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldCreatedAt, v)) +} + +// LastModifiedAt applies equality check predicate on the "last_modified_at" field. It's identical to LastModifiedAtEQ. +func LastModifiedAt(v time.Time) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldLastModifiedAt, v)) +} + // Pid applies equality check predicate on the "pid" field. It's identical to PidEQ. func Pid(v uint64) predicate.Process { return predicate.Process(sql.FieldEQ(FieldPid, v)) @@ -67,6 +80,86 @@ func Principal(v string) predicate.Process { return predicate.Process(sql.FieldEQ(FieldPrincipal, v)) } +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.Process { + return predicate.Process(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.Process { + return predicate.Process(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.Process { + return predicate.Process(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.Process { + return predicate.Process(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.Process { + return predicate.Process(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.Process { + return predicate.Process(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.Process { + return predicate.Process(sql.FieldLTE(FieldCreatedAt, v)) +} + +// LastModifiedAtEQ applies the EQ predicate on the "last_modified_at" field. +func LastModifiedAtEQ(v time.Time) predicate.Process { + return predicate.Process(sql.FieldEQ(FieldLastModifiedAt, v)) +} + +// LastModifiedAtNEQ applies the NEQ predicate on the "last_modified_at" field. +func LastModifiedAtNEQ(v time.Time) predicate.Process { + return predicate.Process(sql.FieldNEQ(FieldLastModifiedAt, v)) +} + +// LastModifiedAtIn applies the In predicate on the "last_modified_at" field. +func LastModifiedAtIn(vs ...time.Time) predicate.Process { + return predicate.Process(sql.FieldIn(FieldLastModifiedAt, vs...)) +} + +// LastModifiedAtNotIn applies the NotIn predicate on the "last_modified_at" field. +func LastModifiedAtNotIn(vs ...time.Time) predicate.Process { + return predicate.Process(sql.FieldNotIn(FieldLastModifiedAt, vs...)) +} + +// LastModifiedAtGT applies the GT predicate on the "last_modified_at" field. +func LastModifiedAtGT(v time.Time) predicate.Process { + return predicate.Process(sql.FieldGT(FieldLastModifiedAt, v)) +} + +// LastModifiedAtGTE applies the GTE predicate on the "last_modified_at" field. +func LastModifiedAtGTE(v time.Time) predicate.Process { + return predicate.Process(sql.FieldGTE(FieldLastModifiedAt, v)) +} + +// LastModifiedAtLT applies the LT predicate on the "last_modified_at" field. +func LastModifiedAtLT(v time.Time) predicate.Process { + return predicate.Process(sql.FieldLT(FieldLastModifiedAt, v)) +} + +// LastModifiedAtLTE applies the LTE predicate on the "last_modified_at" field. +func LastModifiedAtLTE(v time.Time) predicate.Process { + return predicate.Process(sql.FieldLTE(FieldLastModifiedAt, v)) +} + // PidEQ applies the EQ predicate on the "pid" field. func PidEQ(v uint64) predicate.Process { return predicate.Process(sql.FieldEQ(FieldPid, v)) @@ -237,6 +330,52 @@ func PrincipalContainsFold(v string) predicate.Process { return predicate.Process(sql.FieldContainsFold(FieldPrincipal, v)) } +// HasHost applies the HasEdge predicate on the "host" edge. +func HasHost() predicate.Process { + return predicate.Process(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, HostTable, HostColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasHostWith applies the HasEdge predicate on the "host" edge with a given conditions (other predicates). +func HasHostWith(preds ...predicate.Host) predicate.Process { + return predicate.Process(func(s *sql.Selector) { + step := newHostStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasTask applies the HasEdge predicate on the "task" edge. +func HasTask() predicate.Process { + return predicate.Process(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, TaskTable, TaskColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasTaskWith applies the HasEdge predicate on the "task" edge with a given conditions (other predicates). +func HasTaskWith(preds ...predicate.Task) predicate.Process { + return predicate.Process(func(s *sql.Selector) { + step := newTaskStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Process) predicate.Process { return predicate.Process(sql.AndPredicates(predicates...)) diff --git a/tavern/internal/ent/process_create.go b/tavern/internal/ent/process_create.go index 64db05078..e913e2262 100644 --- a/tavern/internal/ent/process_create.go +++ b/tavern/internal/ent/process_create.go @@ -6,11 +6,14 @@ import ( "context" "errors" "fmt" + "time" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/process" + "realm.pub/tavern/internal/ent/task" ) // ProcessCreate is the builder for creating a Process entity. @@ -21,6 +24,34 @@ type ProcessCreate struct { conflict []sql.ConflictOption } +// SetCreatedAt sets the "created_at" field. +func (pc *ProcessCreate) SetCreatedAt(t time.Time) *ProcessCreate { + pc.mutation.SetCreatedAt(t) + return pc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (pc *ProcessCreate) SetNillableCreatedAt(t *time.Time) *ProcessCreate { + if t != nil { + pc.SetCreatedAt(*t) + } + return pc +} + +// SetLastModifiedAt sets the "last_modified_at" field. +func (pc *ProcessCreate) SetLastModifiedAt(t time.Time) *ProcessCreate { + pc.mutation.SetLastModifiedAt(t) + return pc +} + +// SetNillableLastModifiedAt sets the "last_modified_at" field if the given value is not nil. +func (pc *ProcessCreate) SetNillableLastModifiedAt(t *time.Time) *ProcessCreate { + if t != nil { + pc.SetLastModifiedAt(*t) + } + return pc +} + // SetPid sets the "pid" field. func (pc *ProcessCreate) SetPid(u uint64) *ProcessCreate { pc.mutation.SetPid(u) @@ -39,6 +70,28 @@ func (pc *ProcessCreate) SetPrincipal(s string) *ProcessCreate { return pc } +// SetHostID sets the "host" edge to the Host entity by ID. +func (pc *ProcessCreate) SetHostID(id int) *ProcessCreate { + pc.mutation.SetHostID(id) + return pc +} + +// SetHost sets the "host" edge to the Host entity. +func (pc *ProcessCreate) SetHost(h *Host) *ProcessCreate { + return pc.SetHostID(h.ID) +} + +// SetTaskID sets the "task" edge to the Task entity by ID. +func (pc *ProcessCreate) SetTaskID(id int) *ProcessCreate { + pc.mutation.SetTaskID(id) + return pc +} + +// SetTask sets the "task" edge to the Task entity. +func (pc *ProcessCreate) SetTask(t *Task) *ProcessCreate { + return pc.SetTaskID(t.ID) +} + // Mutation returns the ProcessMutation object of the builder. func (pc *ProcessCreate) Mutation() *ProcessMutation { return pc.mutation @@ -46,6 +99,7 @@ func (pc *ProcessCreate) Mutation() *ProcessMutation { // Save creates the Process in the database. func (pc *ProcessCreate) Save(ctx context.Context) (*Process, error) { + pc.defaults() return withHooks(ctx, pc.sqlSave, pc.mutation, pc.hooks) } @@ -71,8 +125,26 @@ func (pc *ProcessCreate) ExecX(ctx context.Context) { } } +// defaults sets the default values of the builder before save. +func (pc *ProcessCreate) defaults() { + if _, ok := pc.mutation.CreatedAt(); !ok { + v := process.DefaultCreatedAt() + pc.mutation.SetCreatedAt(v) + } + if _, ok := pc.mutation.LastModifiedAt(); !ok { + v := process.DefaultLastModifiedAt() + pc.mutation.SetLastModifiedAt(v) + } +} + // check runs all checks and user-defined validators on the builder. func (pc *ProcessCreate) check() error { + if _, ok := pc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Process.created_at"`)} + } + if _, ok := pc.mutation.LastModifiedAt(); !ok { + return &ValidationError{Name: "last_modified_at", err: errors.New(`ent: missing required field "Process.last_modified_at"`)} + } if _, ok := pc.mutation.Pid(); !ok { return &ValidationError{Name: "pid", err: errors.New(`ent: missing required field "Process.pid"`)} } @@ -87,6 +159,12 @@ func (pc *ProcessCreate) check() error { return &ValidationError{Name: "principal", err: fmt.Errorf(`ent: validator failed for field "Process.principal": %w`, err)} } } + if _, ok := pc.mutation.HostID(); !ok { + return &ValidationError{Name: "host", err: errors.New(`ent: missing required edge "Process.host"`)} + } + if _, ok := pc.mutation.TaskID(); !ok { + return &ValidationError{Name: "task", err: errors.New(`ent: missing required edge "Process.task"`)} + } return nil } @@ -114,6 +192,14 @@ func (pc *ProcessCreate) createSpec() (*Process, *sqlgraph.CreateSpec) { _spec = sqlgraph.NewCreateSpec(process.Table, sqlgraph.NewFieldSpec(process.FieldID, field.TypeInt)) ) _spec.OnConflict = pc.conflict + if value, ok := pc.mutation.CreatedAt(); ok { + _spec.SetField(process.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := pc.mutation.LastModifiedAt(); ok { + _spec.SetField(process.FieldLastModifiedAt, field.TypeTime, value) + _node.LastModifiedAt = value + } if value, ok := pc.mutation.Pid(); ok { _spec.SetField(process.FieldPid, field.TypeUint64, value) _node.Pid = value @@ -126,6 +212,40 @@ func (pc *ProcessCreate) createSpec() (*Process, *sqlgraph.CreateSpec) { _spec.SetField(process.FieldPrincipal, field.TypeString, value) _node.Principal = value } + if nodes := pc.mutation.HostIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: process.HostTable, + Columns: []string{process.HostColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(host.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.process_host = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := pc.mutation.TaskIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: process.TaskTable, + Columns: []string{process.TaskColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(task.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.task_reported_processes = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } @@ -133,7 +253,7 @@ func (pc *ProcessCreate) createSpec() (*Process, *sqlgraph.CreateSpec) { // of the `INSERT` statement. For example: // // client.Process.Create(). -// SetPid(v). +// SetCreatedAt(v). // OnConflict( // // Update the row with the new values // // the was proposed for insertion. @@ -142,7 +262,7 @@ func (pc *ProcessCreate) createSpec() (*Process, *sqlgraph.CreateSpec) { // // Override some of the fields with custom // // update values. // Update(func(u *ent.ProcessUpsert) { -// SetPid(v+v). +// SetCreatedAt(v+v). // }). // Exec(ctx) func (pc *ProcessCreate) OnConflict(opts ...sql.ConflictOption) *ProcessUpsertOne { @@ -178,6 +298,18 @@ type ( } ) +// SetLastModifiedAt sets the "last_modified_at" field. +func (u *ProcessUpsert) SetLastModifiedAt(v time.Time) *ProcessUpsert { + u.Set(process.FieldLastModifiedAt, v) + return u +} + +// UpdateLastModifiedAt sets the "last_modified_at" field to the value that was provided on create. +func (u *ProcessUpsert) UpdateLastModifiedAt() *ProcessUpsert { + u.SetExcluded(process.FieldLastModifiedAt) + return u +} + // SetPid sets the "pid" field. func (u *ProcessUpsert) SetPid(v uint64) *ProcessUpsert { u.Set(process.FieldPid, v) @@ -230,6 +362,11 @@ func (u *ProcessUpsert) UpdatePrincipal() *ProcessUpsert { // Exec(ctx) func (u *ProcessUpsertOne) UpdateNewValues() *ProcessUpsertOne { u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.CreatedAt(); exists { + s.SetIgnore(process.FieldCreatedAt) + } + })) return u } @@ -260,6 +397,20 @@ func (u *ProcessUpsertOne) Update(set func(*ProcessUpsert)) *ProcessUpsertOne { return u } +// SetLastModifiedAt sets the "last_modified_at" field. +func (u *ProcessUpsertOne) SetLastModifiedAt(v time.Time) *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.SetLastModifiedAt(v) + }) +} + +// UpdateLastModifiedAt sets the "last_modified_at" field to the value that was provided on create. +func (u *ProcessUpsertOne) UpdateLastModifiedAt() *ProcessUpsertOne { + return u.Update(func(s *ProcessUpsert) { + s.UpdateLastModifiedAt() + }) +} + // SetPid sets the "pid" field. func (u *ProcessUpsertOne) SetPid(v uint64) *ProcessUpsertOne { return u.Update(func(s *ProcessUpsert) { @@ -361,6 +512,7 @@ func (pcb *ProcessCreateBulk) Save(ctx context.Context) ([]*Process, error) { for i := range pcb.builders { func(i int, root context.Context) { builder := pcb.builders[i] + builder.defaults() var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { mutation, ok := m.(*ProcessMutation) if !ok { @@ -443,7 +595,7 @@ func (pcb *ProcessCreateBulk) ExecX(ctx context.Context) { // // Override some of the fields with custom // // update values. // Update(func(u *ent.ProcessUpsert) { -// SetPid(v+v). +// SetCreatedAt(v+v). // }). // Exec(ctx) func (pcb *ProcessCreateBulk) OnConflict(opts ...sql.ConflictOption) *ProcessUpsertBulk { @@ -482,6 +634,13 @@ type ProcessUpsertBulk struct { // Exec(ctx) func (u *ProcessUpsertBulk) UpdateNewValues() *ProcessUpsertBulk { u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.CreatedAt(); exists { + s.SetIgnore(process.FieldCreatedAt) + } + } + })) return u } @@ -512,6 +671,20 @@ func (u *ProcessUpsertBulk) Update(set func(*ProcessUpsert)) *ProcessUpsertBulk return u } +// SetLastModifiedAt sets the "last_modified_at" field. +func (u *ProcessUpsertBulk) SetLastModifiedAt(v time.Time) *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.SetLastModifiedAt(v) + }) +} + +// UpdateLastModifiedAt sets the "last_modified_at" field to the value that was provided on create. +func (u *ProcessUpsertBulk) UpdateLastModifiedAt() *ProcessUpsertBulk { + return u.Update(func(s *ProcessUpsert) { + s.UpdateLastModifiedAt() + }) +} + // SetPid sets the "pid" field. func (u *ProcessUpsertBulk) SetPid(v uint64) *ProcessUpsertBulk { return u.Update(func(s *ProcessUpsert) { diff --git a/tavern/internal/ent/process_query.go b/tavern/internal/ent/process_query.go index 3d9580c03..dbcfdc415 100644 --- a/tavern/internal/ent/process_query.go +++ b/tavern/internal/ent/process_query.go @@ -10,8 +10,10 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/predicate" "realm.pub/tavern/internal/ent/process" + "realm.pub/tavern/internal/ent/task" ) // ProcessQuery is the builder for querying Process entities. @@ -21,6 +23,8 @@ type ProcessQuery struct { order []process.OrderOption inters []Interceptor predicates []predicate.Process + withHost *HostQuery + withTask *TaskQuery withFKs bool modifiers []func(*sql.Selector) loadTotal []func(context.Context, []*Process) error @@ -60,6 +64,50 @@ func (pq *ProcessQuery) Order(o ...process.OrderOption) *ProcessQuery { return pq } +// QueryHost chains the current query on the "host" edge. +func (pq *ProcessQuery) QueryHost() *HostQuery { + query := (&HostClient{config: pq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := pq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(process.Table, process.FieldID, selector), + sqlgraph.To(host.Table, host.FieldID), + sqlgraph.Edge(sqlgraph.M2O, false, process.HostTable, process.HostColumn), + ) + fromU = sqlgraph.SetNeighbors(pq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryTask chains the current query on the "task" edge. +func (pq *ProcessQuery) QueryTask() *TaskQuery { + query := (&TaskClient{config: pq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := pq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := pq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(process.Table, process.FieldID, selector), + sqlgraph.To(task.Table, task.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, process.TaskTable, process.TaskColumn), + ) + fromU = sqlgraph.SetNeighbors(pq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Process entity from the query. // Returns a *NotFoundError when no Process was found. func (pq *ProcessQuery) First(ctx context.Context) (*Process, error) { @@ -252,24 +300,48 @@ func (pq *ProcessQuery) Clone() *ProcessQuery { order: append([]process.OrderOption{}, pq.order...), inters: append([]Interceptor{}, pq.inters...), predicates: append([]predicate.Process{}, pq.predicates...), + withHost: pq.withHost.Clone(), + withTask: pq.withTask.Clone(), // clone intermediate query. sql: pq.sql.Clone(), path: pq.path, } } +// WithHost tells the query-builder to eager-load the nodes that are connected to +// the "host" edge. The optional arguments are used to configure the query builder of the edge. +func (pq *ProcessQuery) WithHost(opts ...func(*HostQuery)) *ProcessQuery { + query := (&HostClient{config: pq.config}).Query() + for _, opt := range opts { + opt(query) + } + pq.withHost = query + return pq +} + +// WithTask tells the query-builder to eager-load the nodes that are connected to +// the "task" edge. The optional arguments are used to configure the query builder of the edge. +func (pq *ProcessQuery) WithTask(opts ...func(*TaskQuery)) *ProcessQuery { + query := (&TaskClient{config: pq.config}).Query() + for _, opt := range opts { + opt(query) + } + pq.withTask = query + return pq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // // Example: // // var v []struct { -// Pid uint64 `json:"pid,omitempty"` +// CreatedAt time.Time `json:"created_at,omitempty"` // Count int `json:"count,omitempty"` // } // // client.Process.Query(). -// GroupBy(process.FieldPid). +// GroupBy(process.FieldCreatedAt). // Aggregate(ent.Count()). // Scan(ctx, &v) func (pq *ProcessQuery) GroupBy(field string, fields ...string) *ProcessGroupBy { @@ -287,11 +359,11 @@ func (pq *ProcessQuery) GroupBy(field string, fields ...string) *ProcessGroupBy // Example: // // var v []struct { -// Pid uint64 `json:"pid,omitempty"` +// CreatedAt time.Time `json:"created_at,omitempty"` // } // // client.Process.Query(). -// Select(process.FieldPid). +// Select(process.FieldCreatedAt). // Scan(ctx, &v) func (pq *ProcessQuery) Select(fields ...string) *ProcessSelect { pq.ctx.Fields = append(pq.ctx.Fields, fields...) @@ -334,10 +406,17 @@ func (pq *ProcessQuery) prepareQuery(ctx context.Context) error { func (pq *ProcessQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Process, error) { var ( - nodes = []*Process{} - withFKs = pq.withFKs - _spec = pq.querySpec() + nodes = []*Process{} + withFKs = pq.withFKs + _spec = pq.querySpec() + loadedTypes = [2]bool{ + pq.withHost != nil, + pq.withTask != nil, + } ) + if pq.withHost != nil || pq.withTask != nil { + withFKs = true + } if withFKs { _spec.Node.Columns = append(_spec.Node.Columns, process.ForeignKeys...) } @@ -347,6 +426,7 @@ func (pq *ProcessQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Proc _spec.Assign = func(columns []string, values []any) error { node := &Process{config: pq.config} nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes return node.assignValues(columns, values) } if len(pq.modifiers) > 0 { @@ -361,6 +441,18 @@ func (pq *ProcessQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Proc if len(nodes) == 0 { return nodes, nil } + if query := pq.withHost; query != nil { + if err := pq.loadHost(ctx, query, nodes, nil, + func(n *Process, e *Host) { n.Edges.Host = e }); err != nil { + return nil, err + } + } + if query := pq.withTask; query != nil { + if err := pq.loadTask(ctx, query, nodes, nil, + func(n *Process, e *Task) { n.Edges.Task = e }); err != nil { + return nil, err + } + } for i := range pq.loadTotal { if err := pq.loadTotal[i](ctx, nodes); err != nil { return nil, err @@ -369,6 +461,71 @@ func (pq *ProcessQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Proc return nodes, nil } +func (pq *ProcessQuery) loadHost(ctx context.Context, query *HostQuery, nodes []*Process, init func(*Process), assign func(*Process, *Host)) error { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*Process) + for i := range nodes { + if nodes[i].process_host == nil { + continue + } + fk := *nodes[i].process_host + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(host.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "process_host" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} +func (pq *ProcessQuery) loadTask(ctx context.Context, query *TaskQuery, nodes []*Process, init func(*Process), assign func(*Process, *Task)) error { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*Process) + for i := range nodes { + if nodes[i].task_reported_processes == nil { + continue + } + fk := *nodes[i].task_reported_processes + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(task.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "task_reported_processes" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + func (pq *ProcessQuery) sqlCount(ctx context.Context) (int, error) { _spec := pq.querySpec() if len(pq.modifiers) > 0 { diff --git a/tavern/internal/ent/process_update.go b/tavern/internal/ent/process_update.go index 146a8b6d4..3f9c7dcb0 100644 --- a/tavern/internal/ent/process_update.go +++ b/tavern/internal/ent/process_update.go @@ -6,12 +6,15 @@ import ( "context" "errors" "fmt" + "time" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" + "realm.pub/tavern/internal/ent/host" "realm.pub/tavern/internal/ent/predicate" "realm.pub/tavern/internal/ent/process" + "realm.pub/tavern/internal/ent/task" ) // ProcessUpdate is the builder for updating Process entities. @@ -27,6 +30,12 @@ func (pu *ProcessUpdate) Where(ps ...predicate.Process) *ProcessUpdate { return pu } +// SetLastModifiedAt sets the "last_modified_at" field. +func (pu *ProcessUpdate) SetLastModifiedAt(t time.Time) *ProcessUpdate { + pu.mutation.SetLastModifiedAt(t) + return pu +} + // SetPid sets the "pid" field. func (pu *ProcessUpdate) SetPid(u uint64) *ProcessUpdate { pu.mutation.ResetPid() @@ -52,13 +61,48 @@ func (pu *ProcessUpdate) SetPrincipal(s string) *ProcessUpdate { return pu } +// SetHostID sets the "host" edge to the Host entity by ID. +func (pu *ProcessUpdate) SetHostID(id int) *ProcessUpdate { + pu.mutation.SetHostID(id) + return pu +} + +// SetHost sets the "host" edge to the Host entity. +func (pu *ProcessUpdate) SetHost(h *Host) *ProcessUpdate { + return pu.SetHostID(h.ID) +} + +// SetTaskID sets the "task" edge to the Task entity by ID. +func (pu *ProcessUpdate) SetTaskID(id int) *ProcessUpdate { + pu.mutation.SetTaskID(id) + return pu +} + +// SetTask sets the "task" edge to the Task entity. +func (pu *ProcessUpdate) SetTask(t *Task) *ProcessUpdate { + return pu.SetTaskID(t.ID) +} + // Mutation returns the ProcessMutation object of the builder. func (pu *ProcessUpdate) Mutation() *ProcessMutation { return pu.mutation } +// ClearHost clears the "host" edge to the Host entity. +func (pu *ProcessUpdate) ClearHost() *ProcessUpdate { + pu.mutation.ClearHost() + return pu +} + +// ClearTask clears the "task" edge to the Task entity. +func (pu *ProcessUpdate) ClearTask() *ProcessUpdate { + pu.mutation.ClearTask() + return pu +} + // Save executes the query and returns the number of nodes affected by the update operation. func (pu *ProcessUpdate) Save(ctx context.Context) (int, error) { + pu.defaults() return withHooks(ctx, pu.sqlSave, pu.mutation, pu.hooks) } @@ -84,6 +128,14 @@ func (pu *ProcessUpdate) ExecX(ctx context.Context) { } } +// defaults sets the default values of the builder before save. +func (pu *ProcessUpdate) defaults() { + if _, ok := pu.mutation.LastModifiedAt(); !ok { + v := process.UpdateDefaultLastModifiedAt() + pu.mutation.SetLastModifiedAt(v) + } +} + // check runs all checks and user-defined validators on the builder. func (pu *ProcessUpdate) check() error { if v, ok := pu.mutation.Principal(); ok { @@ -91,6 +143,12 @@ func (pu *ProcessUpdate) check() error { return &ValidationError{Name: "principal", err: fmt.Errorf(`ent: validator failed for field "Process.principal": %w`, err)} } } + if _, ok := pu.mutation.HostID(); pu.mutation.HostCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Process.host"`) + } + if _, ok := pu.mutation.TaskID(); pu.mutation.TaskCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Process.task"`) + } return nil } @@ -106,6 +164,9 @@ func (pu *ProcessUpdate) sqlSave(ctx context.Context) (n int, err error) { } } } + if value, ok := pu.mutation.LastModifiedAt(); ok { + _spec.SetField(process.FieldLastModifiedAt, field.TypeTime, value) + } if value, ok := pu.mutation.Pid(); ok { _spec.SetField(process.FieldPid, field.TypeUint64, value) } @@ -118,6 +179,64 @@ func (pu *ProcessUpdate) sqlSave(ctx context.Context) (n int, err error) { if value, ok := pu.mutation.Principal(); ok { _spec.SetField(process.FieldPrincipal, field.TypeString, value) } + if pu.mutation.HostCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: process.HostTable, + Columns: []string{process.HostColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(host.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := pu.mutation.HostIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: process.HostTable, + Columns: []string{process.HostColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(host.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if pu.mutation.TaskCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: process.TaskTable, + Columns: []string{process.TaskColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(task.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := pu.mutation.TaskIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: process.TaskTable, + Columns: []string{process.TaskColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(task.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{process.Label} @@ -138,6 +257,12 @@ type ProcessUpdateOne struct { mutation *ProcessMutation } +// SetLastModifiedAt sets the "last_modified_at" field. +func (puo *ProcessUpdateOne) SetLastModifiedAt(t time.Time) *ProcessUpdateOne { + puo.mutation.SetLastModifiedAt(t) + return puo +} + // SetPid sets the "pid" field. func (puo *ProcessUpdateOne) SetPid(u uint64) *ProcessUpdateOne { puo.mutation.ResetPid() @@ -163,11 +288,45 @@ func (puo *ProcessUpdateOne) SetPrincipal(s string) *ProcessUpdateOne { return puo } +// SetHostID sets the "host" edge to the Host entity by ID. +func (puo *ProcessUpdateOne) SetHostID(id int) *ProcessUpdateOne { + puo.mutation.SetHostID(id) + return puo +} + +// SetHost sets the "host" edge to the Host entity. +func (puo *ProcessUpdateOne) SetHost(h *Host) *ProcessUpdateOne { + return puo.SetHostID(h.ID) +} + +// SetTaskID sets the "task" edge to the Task entity by ID. +func (puo *ProcessUpdateOne) SetTaskID(id int) *ProcessUpdateOne { + puo.mutation.SetTaskID(id) + return puo +} + +// SetTask sets the "task" edge to the Task entity. +func (puo *ProcessUpdateOne) SetTask(t *Task) *ProcessUpdateOne { + return puo.SetTaskID(t.ID) +} + // Mutation returns the ProcessMutation object of the builder. func (puo *ProcessUpdateOne) Mutation() *ProcessMutation { return puo.mutation } +// ClearHost clears the "host" edge to the Host entity. +func (puo *ProcessUpdateOne) ClearHost() *ProcessUpdateOne { + puo.mutation.ClearHost() + return puo +} + +// ClearTask clears the "task" edge to the Task entity. +func (puo *ProcessUpdateOne) ClearTask() *ProcessUpdateOne { + puo.mutation.ClearTask() + return puo +} + // Where appends a list predicates to the ProcessUpdate builder. func (puo *ProcessUpdateOne) Where(ps ...predicate.Process) *ProcessUpdateOne { puo.mutation.Where(ps...) @@ -183,6 +342,7 @@ func (puo *ProcessUpdateOne) Select(field string, fields ...string) *ProcessUpda // Save executes the query and returns the updated Process entity. func (puo *ProcessUpdateOne) Save(ctx context.Context) (*Process, error) { + puo.defaults() return withHooks(ctx, puo.sqlSave, puo.mutation, puo.hooks) } @@ -208,6 +368,14 @@ func (puo *ProcessUpdateOne) ExecX(ctx context.Context) { } } +// defaults sets the default values of the builder before save. +func (puo *ProcessUpdateOne) defaults() { + if _, ok := puo.mutation.LastModifiedAt(); !ok { + v := process.UpdateDefaultLastModifiedAt() + puo.mutation.SetLastModifiedAt(v) + } +} + // check runs all checks and user-defined validators on the builder. func (puo *ProcessUpdateOne) check() error { if v, ok := puo.mutation.Principal(); ok { @@ -215,6 +383,12 @@ func (puo *ProcessUpdateOne) check() error { return &ValidationError{Name: "principal", err: fmt.Errorf(`ent: validator failed for field "Process.principal": %w`, err)} } } + if _, ok := puo.mutation.HostID(); puo.mutation.HostCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Process.host"`) + } + if _, ok := puo.mutation.TaskID(); puo.mutation.TaskCleared() && !ok { + return errors.New(`ent: clearing a required unique edge "Process.task"`) + } return nil } @@ -247,6 +421,9 @@ func (puo *ProcessUpdateOne) sqlSave(ctx context.Context) (_node *Process, err e } } } + if value, ok := puo.mutation.LastModifiedAt(); ok { + _spec.SetField(process.FieldLastModifiedAt, field.TypeTime, value) + } if value, ok := puo.mutation.Pid(); ok { _spec.SetField(process.FieldPid, field.TypeUint64, value) } @@ -259,6 +436,64 @@ func (puo *ProcessUpdateOne) sqlSave(ctx context.Context) (_node *Process, err e if value, ok := puo.mutation.Principal(); ok { _spec.SetField(process.FieldPrincipal, field.TypeString, value) } + if puo.mutation.HostCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: process.HostTable, + Columns: []string{process.HostColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(host.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := puo.mutation.HostIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: false, + Table: process.HostTable, + Columns: []string{process.HostColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(host.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if puo.mutation.TaskCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: process.TaskTable, + Columns: []string{process.TaskColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(task.FieldID, field.TypeInt), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := puo.mutation.TaskIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: process.TaskTable, + Columns: []string{process.TaskColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(task.FieldID, field.TypeInt), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _node = &Process{config: puo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/tavern/internal/ent/runtime/runtime.go b/tavern/internal/ent/runtime/runtime.go index 6c1faadb3..3190980f6 100644 --- a/tavern/internal/ent/runtime/runtime.go +++ b/tavern/internal/ent/runtime/runtime.go @@ -84,8 +84,21 @@ func init() { hostDescName := hostFields[1].Descriptor() // host.NameValidator is a validator for the "name" field. It is called by the builders before save. host.NameValidator = hostDescName.Validators[0].(func(string) error) + processMixin := schema.Process{}.Mixin() + processMixinFields0 := processMixin[0].Fields() + _ = processMixinFields0 processFields := schema.Process{}.Fields() _ = processFields + // processDescCreatedAt is the schema descriptor for created_at field. + processDescCreatedAt := processMixinFields0[0].Descriptor() + // process.DefaultCreatedAt holds the default value on creation for the created_at field. + process.DefaultCreatedAt = processDescCreatedAt.Default.(func() time.Time) + // processDescLastModifiedAt is the schema descriptor for last_modified_at field. + processDescLastModifiedAt := processMixinFields0[1].Descriptor() + // process.DefaultLastModifiedAt holds the default value on creation for the last_modified_at field. + process.DefaultLastModifiedAt = processDescLastModifiedAt.Default.(func() time.Time) + // process.UpdateDefaultLastModifiedAt holds the default value on update for the last_modified_at field. + process.UpdateDefaultLastModifiedAt = processDescLastModifiedAt.UpdateDefault.(func() time.Time) // processDescPrincipal is the schema descriptor for principal field. processDescPrincipal := processFields[2].Descriptor() // process.PrincipalValidator is a validator for the "principal" field. It is called by the builders before save. diff --git a/tavern/internal/ent/schema/host.go b/tavern/internal/ent/schema/host.go index 04da1c66b..4fe495cdf 100644 --- a/tavern/internal/ent/schema/host.go +++ b/tavern/internal/ent/schema/host.go @@ -58,6 +58,8 @@ func (Host) Edges() []ent.Edge { edge.From("beacons", Beacon.Type). Ref("host"). Comment("Beacons that are present on this host system."), + edge.To("processes", Process.Type). + Comment("Processes reported as running on this host system."), } } diff --git a/tavern/internal/ent/schema/process.go b/tavern/internal/ent/schema/process.go index c05cf7774..8ecfa55ce 100644 --- a/tavern/internal/ent/schema/process.go +++ b/tavern/internal/ent/schema/process.go @@ -1,8 +1,10 @@ package schema import ( + "entgo.io/contrib/entgql" "entgo.io/ent" "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" ) @@ -15,8 +17,14 @@ type Process struct { func (Process) Fields() []ent.Field { return []ent.Field{ field.Uint64("pid"). + Annotations( + entgql.OrderField("PROCESS_ID"), + ). Comment("ID of the process."), field.String("name"). + Annotations( + entgql.OrderField("NAME"), + ). Comment("The name of the process."), field.String("principal"). NotEmpty(). @@ -27,28 +35,26 @@ func (Process) Fields() []ent.Field { // Edges of the ent. func (Process) Edges() []ent.Edge { return []ent.Edge{ - // edge.To("host", Host.Type). - // Required(). - // Unique(). - // Comment("Host the process was reported on."), - // edge.From("task", Task.Type). - // Required(). - // Unique(). - // Ref("reported_processes"). - // Comment("Task that reported this process."), + edge.To("host", Host.Type). + Required(). + Unique(). + Comment("Host the process was reported on."), + edge.From("task", Task.Type). + Required(). + Unique(). + Ref("reported_processes"). + Comment("Task that reported this process."), } } // Annotations describes additional information for the ent. func (Process) Annotations() []schema.Annotation { - return []schema.Annotation{ - // entgql.Skip(entgql.SkipMutationCreateInput, entgql.SkipMutationUpdateInput), - } + return []schema.Annotation{} } // Mixin defines common shared properties for the ent. func (Process) Mixin() []ent.Mixin { return []ent.Mixin{ - // MixinHistory{}, // created_at, last_modified_at + MixinHistory{}, // created_at, last_modified_at } } diff --git a/tavern/internal/graphql/generated/ent.generated.go b/tavern/internal/graphql/generated/ent.generated.go index cf4f29249..d0c0da9c5 100644 --- a/tavern/internal/graphql/generated/ent.generated.go +++ b/tavern/internal/graphql/generated/ent.generated.go @@ -623,6 +623,8 @@ func (ec *executionContext) fieldContext_Beacon_host(ctx context.Context, field return ec.fieldContext_Host_tags(ctx, field) case "beacons": return ec.fieldContext_Host_beacons(ctx, field) + case "processes": + return ec.fieldContext_Host_processes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Host", field.Name) }, @@ -1387,6 +1389,65 @@ func (ec *executionContext) fieldContext_Host_beacons(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Host_processes(ctx context.Context, field graphql.CollectedField, obj *ent.Host) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Host_processes(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.Processes(ctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*ent.Process) + fc.Result = res + return ec.marshalOProcess2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Host_processes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Host", + 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_Process_id(ctx, field) + case "createdAt": + return ec.fieldContext_Process_createdAt(ctx, field) + case "lastModifiedAt": + return ec.fieldContext_Process_lastModifiedAt(ctx, field) + case "pid": + return ec.fieldContext_Process_pid(ctx, field) + case "name": + return ec.fieldContext_Process_name(ctx, field) + case "principal": + return ec.fieldContext_Process_principal(ctx, field) + case "host": + return ec.fieldContext_Process_host(ctx, field) + case "task": + return ec.fieldContext_Process_task(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Process", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *entgql.PageInfo[int]) (ret graphql.Marshaler) { fc, err := ec.fieldContext_PageInfo_hasNextPage(ctx, field) if err != nil { @@ -1601,6 +1662,94 @@ func (ec *executionContext) fieldContext_Process_id(ctx context.Context, field g return fc, nil } +func (ec *executionContext) _Process_createdAt(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_createdAt(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.CreatedAt, 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_Process_createdAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + 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) _Process_lastModifiedAt(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_lastModifiedAt(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.LastModifiedAt, 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_Process_lastModifiedAt(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + 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) _Process_pid(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Process_pid(ctx, field) if err != nil { @@ -1733,6 +1882,140 @@ func (ec *executionContext) fieldContext_Process_principal(ctx context.Context, return fc, nil } +func (ec *executionContext) _Process_host(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_host(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.Host(ctx) + }) + 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.(*ent.Host) + fc.Result = res + return ec.marshalNHost2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐHost(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Process_host(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + 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_Host_id(ctx, field) + case "identifier": + return ec.fieldContext_Host_identifier(ctx, field) + case "name": + return ec.fieldContext_Host_name(ctx, field) + case "primaryIP": + return ec.fieldContext_Host_primaryIP(ctx, field) + case "platform": + return ec.fieldContext_Host_platform(ctx, field) + case "lastSeenAt": + return ec.fieldContext_Host_lastSeenAt(ctx, field) + case "tags": + return ec.fieldContext_Host_tags(ctx, field) + case "beacons": + return ec.fieldContext_Host_beacons(ctx, field) + case "processes": + return ec.fieldContext_Host_processes(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Host", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Process_task(ctx context.Context, field graphql.CollectedField, obj *ent.Process) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Process_task(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.Task(ctx) + }) + 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.(*ent.Task) + fc.Result = res + return ec.marshalNTask2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐTask(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Process_task(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Process", + 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_Task_id(ctx, field) + case "createdAt": + return ec.fieldContext_Task_createdAt(ctx, field) + case "lastModifiedAt": + return ec.fieldContext_Task_lastModifiedAt(ctx, field) + case "claimedAt": + return ec.fieldContext_Task_claimedAt(ctx, field) + case "execStartedAt": + return ec.fieldContext_Task_execStartedAt(ctx, field) + case "execFinishedAt": + return ec.fieldContext_Task_execFinishedAt(ctx, field) + case "output": + return ec.fieldContext_Task_output(ctx, field) + case "outputSize": + return ec.fieldContext_Task_outputSize(ctx, field) + case "error": + return ec.fieldContext_Task_error(ctx, field) + case "quest": + return ec.fieldContext_Task_quest(ctx, field) + case "beacon": + return ec.fieldContext_Task_beacon(ctx, field) + case "reportedProcesses": + return ec.fieldContext_Task_reportedProcesses(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Task", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_node(ctx, field) if err != nil { @@ -2299,6 +2582,8 @@ func (ec *executionContext) fieldContext_Query_hosts(ctx context.Context, field return ec.fieldContext_Host_tags(ctx, field) case "beacons": return ec.fieldContext_Host_beacons(ctx, field) + case "processes": + return ec.fieldContext_Host_processes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Host", field.Name) }, @@ -3419,6 +3704,8 @@ func (ec *executionContext) fieldContext_Tag_hosts(ctx context.Context, field gr return ec.fieldContext_Host_tags(ctx, field) case "beacons": return ec.fieldContext_Host_beacons(ctx, field) + case "processes": + return ec.fieldContext_Host_processes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Host", field.Name) }, @@ -3973,12 +4260,20 @@ func (ec *executionContext) fieldContext_Task_reportedProcesses(ctx context.Cont switch field.Name { case "id": return ec.fieldContext_Process_id(ctx, field) + case "createdAt": + return ec.fieldContext_Process_createdAt(ctx, field) + case "lastModifiedAt": + return ec.fieldContext_Process_lastModifiedAt(ctx, field) case "pid": return ec.fieldContext_Process_pid(ctx, field) case "name": return ec.fieldContext_Process_name(ctx, field) case "principal": return ec.fieldContext_Process_principal(ctx, field) + case "host": + return ec.fieldContext_Process_host(ctx, field) + case "task": + return ec.fieldContext_Process_task(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Process", field.Name) }, @@ -6546,7 +6841,7 @@ func (ec *executionContext) unmarshalInputHostWhereInput(ctx context.Context, ob asMap[k] = v } - fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "identifier", "identifierNEQ", "identifierIn", "identifierNotIn", "identifierGT", "identifierGTE", "identifierLT", "identifierLTE", "identifierContains", "identifierHasPrefix", "identifierHasSuffix", "identifierEqualFold", "identifierContainsFold", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameIsNil", "nameNotNil", "nameEqualFold", "nameContainsFold", "primaryIP", "primaryIPNEQ", "primaryIPIn", "primaryIPNotIn", "primaryIPGT", "primaryIPGTE", "primaryIPLT", "primaryIPLTE", "primaryIPContains", "primaryIPHasPrefix", "primaryIPHasSuffix", "primaryIPIsNil", "primaryIPNotNil", "primaryIPEqualFold", "primaryIPContainsFold", "platform", "platformNEQ", "platformIn", "platformNotIn", "lastSeenAt", "lastSeenAtNEQ", "lastSeenAtIn", "lastSeenAtNotIn", "lastSeenAtGT", "lastSeenAtGTE", "lastSeenAtLT", "lastSeenAtLTE", "lastSeenAtIsNil", "lastSeenAtNotNil", "hasTags", "hasTagsWith", "hasBeacons", "hasBeaconsWith"} + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "identifier", "identifierNEQ", "identifierIn", "identifierNotIn", "identifierGT", "identifierGTE", "identifierLT", "identifierLTE", "identifierContains", "identifierHasPrefix", "identifierHasSuffix", "identifierEqualFold", "identifierContainsFold", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameIsNil", "nameNotNil", "nameEqualFold", "nameContainsFold", "primaryIP", "primaryIPNEQ", "primaryIPIn", "primaryIPNotIn", "primaryIPGT", "primaryIPGTE", "primaryIPLT", "primaryIPLTE", "primaryIPContains", "primaryIPHasPrefix", "primaryIPHasSuffix", "primaryIPIsNil", "primaryIPNotNil", "primaryIPEqualFold", "primaryIPContainsFold", "platform", "platformNEQ", "platformIn", "platformNotIn", "lastSeenAt", "lastSeenAtNEQ", "lastSeenAtIn", "lastSeenAtNotIn", "lastSeenAtGT", "lastSeenAtGTE", "lastSeenAtLT", "lastSeenAtLTE", "lastSeenAtIsNil", "lastSeenAtNotNil", "hasTags", "hasTagsWith", "hasBeacons", "hasBeaconsWith", "hasProcesses", "hasProcessesWith"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -7201,6 +7496,66 @@ func (ec *executionContext) unmarshalInputHostWhereInput(ctx context.Context, ob return it, err } it.HasBeaconsWith = data + case "hasProcesses": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasProcesses")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.HasProcesses = data + case "hasProcessesWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasProcessesWith")) + data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.HasProcessesWith = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputProcessOrder(ctx context.Context, obj interface{}) (ent.ProcessOrder, error) { + var it ent.ProcessOrder + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + if _, present := asMap["direction"]; !present { + asMap["direction"] = "ASC" + } + + fieldsInOrder := [...]string{"direction", "field"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "direction": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) + data, err := ec.unmarshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚐOrderDirection(ctx, v) + if err != nil { + return it, err + } + it.Direction = data + case "field": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) + data, err := ec.unmarshalNProcessOrderField2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessOrderField(ctx, v) + if err != nil { + return it, err + } + it.Field = data } } @@ -7214,7 +7569,7 @@ func (ec *executionContext) unmarshalInputProcessWhereInput(ctx context.Context, asMap[k] = v } - fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "pid", "pidNEQ", "pidIn", "pidNotIn", "pidGT", "pidGTE", "pidLT", "pidLTE", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameEqualFold", "nameContainsFold", "principal", "principalNEQ", "principalIn", "principalNotIn", "principalGT", "principalGTE", "principalLT", "principalLTE", "principalContains", "principalHasPrefix", "principalHasSuffix", "principalEqualFold", "principalContainsFold"} + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "createdAt", "createdAtNEQ", "createdAtIn", "createdAtNotIn", "createdAtGT", "createdAtGTE", "createdAtLT", "createdAtLTE", "lastModifiedAt", "lastModifiedAtNEQ", "lastModifiedAtIn", "lastModifiedAtNotIn", "lastModifiedAtGT", "lastModifiedAtGTE", "lastModifiedAtLT", "lastModifiedAtLTE", "pid", "pidNEQ", "pidIn", "pidNotIn", "pidGT", "pidGTE", "pidLT", "pidLTE", "name", "nameNEQ", "nameIn", "nameNotIn", "nameGT", "nameGTE", "nameLT", "nameLTE", "nameContains", "nameHasPrefix", "nameHasSuffix", "nameEqualFold", "nameContainsFold", "principal", "principalNEQ", "principalIn", "principalNotIn", "principalGT", "principalGTE", "principalLT", "principalLTE", "principalContains", "principalHasPrefix", "principalHasSuffix", "principalEqualFold", "principalContainsFold", "hasHost", "hasHostWith", "hasTask", "hasTaskWith"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -7224,102 +7579,246 @@ func (ec *executionContext) unmarshalInputProcessWhereInput(ctx context.Context, case "not": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) - data, err := ec.unmarshalOProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + data, err := ec.unmarshalOProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx, v) + if err != nil { + return it, err + } + it.Not = data + case "and": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.And = data + case "or": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.Or = data + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.ID = data + case "idNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDNEQ = data + case "idIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + it.IDIn = data + case "idNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + it.IDNotIn = data + case "idGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDGT = data + case "idGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDGTE = data + case "idLT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDLT = data + case "idLTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + data, err := ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.IDLTE = data + case "createdAt": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAt")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + it.CreatedAt = data + case "createdAtNEQ": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtNEQ")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + it.CreatedAtNEQ = data + case "createdAtIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtIn")) + data, err := ec.unmarshalOTime2ᚕtimeᚐTimeᚄ(ctx, v) + if err != nil { + return it, err + } + it.CreatedAtIn = data + case "createdAtNotIn": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtNotIn")) + data, err := ec.unmarshalOTime2ᚕtimeᚐTimeᚄ(ctx, v) + if err != nil { + return it, err + } + it.CreatedAtNotIn = data + case "createdAtGT": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtGT")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) + if err != nil { + return it, err + } + it.CreatedAtGT = data + case "createdAtGTE": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtGTE")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.Not = data - case "and": + it.CreatedAtGTE = data + case "createdAtLT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) - data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtLT")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.And = data - case "or": + it.CreatedAtLT = data + case "createdAtLTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) - data, err := ec.unmarshalOProcessWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInputᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("createdAtLTE")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.Or = data - case "id": + it.CreatedAtLTE = data + case "lastModifiedAt": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - data, err := ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAt")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.ID = data - case "idNEQ": + it.LastModifiedAt = data + case "lastModifiedAtNEQ": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) - data, err := ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtNEQ")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.IDNEQ = data - case "idIn": + it.LastModifiedAtNEQ = data + case "lastModifiedAtIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) - data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtIn")) + data, err := ec.unmarshalOTime2ᚕtimeᚐTimeᚄ(ctx, v) if err != nil { return it, err } - it.IDIn = data - case "idNotIn": + it.LastModifiedAtIn = data + case "lastModifiedAtNotIn": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) - data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtNotIn")) + data, err := ec.unmarshalOTime2ᚕtimeᚐTimeᚄ(ctx, v) if err != nil { return it, err } - it.IDNotIn = data - case "idGT": + it.LastModifiedAtNotIn = data + case "lastModifiedAtGT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) - data, err := ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtGT")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.IDGT = data - case "idGTE": + it.LastModifiedAtGT = data + case "lastModifiedAtGTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) - data, err := ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtGTE")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.IDGTE = data - case "idLT": + it.LastModifiedAtGTE = data + case "lastModifiedAtLT": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) - data, err := ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtLT")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.IDLT = data - case "idLTE": + it.LastModifiedAtLT = data + case "lastModifiedAtLTE": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) - data, err := ec.unmarshalOID2ᚖint(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("lastModifiedAtLTE")) + data, err := ec.unmarshalOTime2ᚖtimeᚐTime(ctx, v) if err != nil { return it, err } - it.IDLTE = data + it.LastModifiedAtLTE = data case "pid": var err error @@ -7642,6 +8141,42 @@ func (ec *executionContext) unmarshalInputProcessWhereInput(ctx context.Context, return it, err } it.PrincipalContainsFold = data + case "hasHost": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasHost")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.HasHost = data + case "hasHostWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasHostWith")) + data, err := ec.unmarshalOHostWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐHostWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.HasHostWith = data + case "hasTask": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTask")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.HasTask = data + case "hasTaskWith": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTaskWith")) + data, err := ec.unmarshalOTaskWhereInput2ᚕᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐTaskWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.HasTaskWith = data } } @@ -10425,7 +10960,7 @@ func (ec *executionContext) unmarshalInputUpdateHostInput(ctx context.Context, o asMap[k] = v } - fieldsInOrder := [...]string{"name", "clearName", "addTagIDs", "removeTagIDs", "clearTags", "addBeaconIDs", "removeBeaconIDs", "clearBeacons"} + fieldsInOrder := [...]string{"name", "clearName", "addTagIDs", "removeTagIDs", "clearTags", "addBeaconIDs", "removeBeaconIDs", "clearBeacons", "addProcessIDs", "removeProcessIDs", "clearProcesses"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -10504,6 +11039,33 @@ func (ec *executionContext) unmarshalInputUpdateHostInput(ctx context.Context, o return it, err } it.ClearBeacons = data + case "addProcessIDs": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("addProcessIDs")) + data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + it.AddProcessIDs = data + case "removeProcessIDs": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("removeProcessIDs")) + data, err := ec.unmarshalOID2ᚕintᚄ(ctx, v) + if err != nil { + return it, err + } + it.RemoveProcessIDs = data + case "clearProcesses": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("clearProcesses")) + data, err := ec.unmarshalOBoolean2bool(ctx, v) + if err != nil { + return it, err + } + it.ClearProcesses = data } } @@ -11402,6 +11964,39 @@ func (ec *executionContext) _Host(ctx context.Context, sel ast.SelectionSet, obj continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "processes": + 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._Host_processes(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) @@ -11490,6 +12085,16 @@ func (ec *executionContext) _Process(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "createdAt": + out.Values[i] = ec._Process_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "lastModifiedAt": + out.Values[i] = ec._Process_lastModifiedAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } case "pid": field := field @@ -11536,6 +12141,78 @@ func (ec *executionContext) _Process(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "host": + 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._Process_host(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 "task": + 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._Process_task(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)) } @@ -12869,6 +13546,22 @@ func (ec *executionContext) marshalNProcess2ᚖrealmᚗpubᚋtavernᚋinternal return ec._Process(ctx, sel, v) } +func (ec *executionContext) unmarshalNProcessOrderField2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessOrderField(ctx context.Context, v interface{}) (*ent.ProcessOrderField, error) { + var res = new(ent.ProcessOrderField) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNProcessOrderField2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessOrderField(ctx context.Context, sel ast.SelectionSet, v *ent.ProcessOrderField) 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 v +} + func (ec *executionContext) unmarshalNProcessWhereInput2ᚖrealmᚗpubᚋtavernᚋinternalᚋentᚐProcessWhereInput(ctx context.Context, v interface{}) (*ent.ProcessWhereInput, error) { res, err := ec.unmarshalInputProcessWhereInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) diff --git a/tavern/internal/graphql/generated/mutation.generated.go b/tavern/internal/graphql/generated/mutation.generated.go index 4dc19521b..46f97c766 100644 --- a/tavern/internal/graphql/generated/mutation.generated.go +++ b/tavern/internal/graphql/generated/mutation.generated.go @@ -495,6 +495,8 @@ func (ec *executionContext) fieldContext_Mutation_updateHost(ctx context.Context return ec.fieldContext_Host_tags(ctx, field) case "beacons": return ec.fieldContext_Host_beacons(ctx, field) + case "processes": + return ec.fieldContext_Host_processes(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type Host", field.Name) }, diff --git a/tavern/internal/graphql/generated/root_.generated.go b/tavern/internal/graphql/generated/root_.generated.go index 595e99bb3..28a7705ab 100644 --- a/tavern/internal/graphql/generated/root_.generated.go +++ b/tavern/internal/graphql/generated/root_.generated.go @@ -76,6 +76,7 @@ type ComplexityRoot struct { Name func(childComplexity int) int Platform func(childComplexity int) int PrimaryIP func(childComplexity int) int + Processes func(childComplexity int) int Tags func(childComplexity int) int } @@ -99,10 +100,14 @@ type ComplexityRoot struct { } Process struct { - ID func(childComplexity int) int - Name func(childComplexity int) int - Pid func(childComplexity int) int - Principal func(childComplexity int) int + CreatedAt func(childComplexity int) int + Host func(childComplexity int) int + ID func(childComplexity int) int + LastModifiedAt func(childComplexity int) int + Name func(childComplexity int) int + Pid func(childComplexity int) int + Principal func(childComplexity int) int + Task func(childComplexity int) int } Query struct { @@ -364,6 +369,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Host.PrimaryIP(childComplexity), true + case "Host.processes": + if e.complexity.Host.Processes == nil { + break + } + + return e.complexity.Host.Processes(childComplexity), true + case "Host.tags": if e.complexity.Host.Tags == nil { break @@ -507,6 +519,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PageInfo.StartCursor(childComplexity), true + case "Process.createdAt": + if e.complexity.Process.CreatedAt == nil { + break + } + + return e.complexity.Process.CreatedAt(childComplexity), true + + case "Process.host": + if e.complexity.Process.Host == nil { + break + } + + return e.complexity.Process.Host(childComplexity), true + case "Process.id": if e.complexity.Process.ID == nil { break @@ -514,6 +540,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Process.ID(childComplexity), true + case "Process.lastModifiedAt": + if e.complexity.Process.LastModifiedAt == nil { + break + } + + return e.complexity.Process.LastModifiedAt(childComplexity), true + case "Process.name": if e.complexity.Process.Name == nil { break @@ -535,6 +568,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Process.Principal(childComplexity), true + case "Process.task": + if e.complexity.Process.Task == nil { + break + } + + return e.complexity.Process.Task(childComplexity), true + case "Query.beacons": if e.complexity.Query.Beacons == nil { break @@ -981,6 +1021,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputFileWhereInput, ec.unmarshalInputHostOrder, ec.unmarshalInputHostWhereInput, + ec.unmarshalInputProcessOrder, ec.unmarshalInputProcessWhereInput, ec.unmarshalInputQuestOrder, ec.unmarshalInputQuestWhereInput, @@ -1400,6 +1441,8 @@ type Host implements Node { tags: [Tag!] """Beacons that are present on this host system.""" beacons: [Beacon!] + """Processes reported as running on this host system.""" + processes: [Process!] } """Ordering options for Host connections""" input HostOrder { @@ -1505,6 +1548,9 @@ input HostWhereInput { """beacons edge predicates""" hasBeacons: Boolean hasBeaconsWith: [BeaconWhereInput!] + """processes edge predicates""" + hasProcesses: Boolean + hasProcessesWith: [ProcessWhereInput!] } """ An object with an ID. @@ -1537,12 +1583,34 @@ type PageInfo { } type Process implements Node { id: ID! + """Timestamp of when this ent was created""" + createdAt: Time! + """Timestamp of when this ent was last updated""" + lastModifiedAt: Time! """ID of the process.""" pid: Int! """The name of the process.""" name: String! """The user the process is running as.""" principal: String! + """Host the process was reported on.""" + host: Host! + """Task that reported this process.""" + task: Task! +} +"""Ordering options for Process connections""" +input ProcessOrder { + """The ordering direction.""" + direction: OrderDirection! = ASC + """The field by which to order Processes.""" + field: ProcessOrderField! +} +"""Properties by which Process connections can be ordered.""" +enum ProcessOrderField { + CREATED_AT + LAST_MODIFIED_AT + PROCESS_ID + NAME } """ ProcessWhereInput is used for filtering Process objects. @@ -1561,6 +1629,24 @@ input ProcessWhereInput { idGTE: ID idLT: ID idLTE: ID + """created_at field predicates""" + createdAt: Time + createdAtNEQ: Time + createdAtIn: [Time!] + createdAtNotIn: [Time!] + createdAtGT: Time + createdAtGTE: Time + createdAtLT: Time + createdAtLTE: Time + """last_modified_at field predicates""" + lastModifiedAt: Time + lastModifiedAtNEQ: Time + lastModifiedAtIn: [Time!] + lastModifiedAtNotIn: [Time!] + lastModifiedAtGT: Time + lastModifiedAtGTE: Time + lastModifiedAtLT: Time + lastModifiedAtLTE: Time """pid field predicates""" pid: Int pidNEQ: Int @@ -1598,6 +1684,12 @@ input ProcessWhereInput { principalHasSuffix: String principalEqualFold: String principalContainsFold: String + """host edge predicates""" + hasHost: Boolean + hasHostWith: [HostWhereInput!] + """task edge predicates""" + hasTask: Boolean + hasTaskWith: [TaskWhereInput!] } type Query { """Fetches an object given its ID.""" @@ -2107,6 +2199,9 @@ input UpdateHostInput { addBeaconIDs: [ID!] removeBeaconIDs: [ID!] clearBeacons: Boolean + addProcessIDs: [ID!] + removeProcessIDs: [ID!] + clearProcesses: Boolean } """ UpdateTagInput is used for update Tag object. diff --git a/tavern/internal/graphql/schema.graphql b/tavern/internal/graphql/schema.graphql index d51b3b058..9873e5171 100644 --- a/tavern/internal/graphql/schema.graphql +++ b/tavern/internal/graphql/schema.graphql @@ -304,6 +304,8 @@ type Host implements Node { tags: [Tag!] """Beacons that are present on this host system.""" beacons: [Beacon!] + """Processes reported as running on this host system.""" + processes: [Process!] } """Ordering options for Host connections""" input HostOrder { @@ -409,6 +411,9 @@ input HostWhereInput { """beacons edge predicates""" hasBeacons: Boolean hasBeaconsWith: [BeaconWhereInput!] + """processes edge predicates""" + hasProcesses: Boolean + hasProcessesWith: [ProcessWhereInput!] } """ An object with an ID. @@ -441,12 +446,34 @@ type PageInfo { } type Process implements Node { id: ID! + """Timestamp of when this ent was created""" + createdAt: Time! + """Timestamp of when this ent was last updated""" + lastModifiedAt: Time! """ID of the process.""" pid: Int! """The name of the process.""" name: String! """The user the process is running as.""" principal: String! + """Host the process was reported on.""" + host: Host! + """Task that reported this process.""" + task: Task! +} +"""Ordering options for Process connections""" +input ProcessOrder { + """The ordering direction.""" + direction: OrderDirection! = ASC + """The field by which to order Processes.""" + field: ProcessOrderField! +} +"""Properties by which Process connections can be ordered.""" +enum ProcessOrderField { + CREATED_AT + LAST_MODIFIED_AT + PROCESS_ID + NAME } """ ProcessWhereInput is used for filtering Process objects. @@ -465,6 +492,24 @@ input ProcessWhereInput { idGTE: ID idLT: ID idLTE: ID + """created_at field predicates""" + createdAt: Time + createdAtNEQ: Time + createdAtIn: [Time!] + createdAtNotIn: [Time!] + createdAtGT: Time + createdAtGTE: Time + createdAtLT: Time + createdAtLTE: Time + """last_modified_at field predicates""" + lastModifiedAt: Time + lastModifiedAtNEQ: Time + lastModifiedAtIn: [Time!] + lastModifiedAtNotIn: [Time!] + lastModifiedAtGT: Time + lastModifiedAtGTE: Time + lastModifiedAtLT: Time + lastModifiedAtLTE: Time """pid field predicates""" pid: Int pidNEQ: Int @@ -502,6 +547,12 @@ input ProcessWhereInput { principalHasSuffix: String principalEqualFold: String principalContainsFold: String + """host edge predicates""" + hasHost: Boolean + hasHostWith: [HostWhereInput!] + """task edge predicates""" + hasTask: Boolean + hasTaskWith: [TaskWhereInput!] } type Query { """Fetches an object given its ID.""" @@ -1011,6 +1062,9 @@ input UpdateHostInput { addBeaconIDs: [ID!] removeBeaconIDs: [ID!] clearBeacons: Boolean + addProcessIDs: [ID!] + removeProcessIDs: [ID!] + clearProcesses: Boolean } """ UpdateTagInput is used for update Tag object. diff --git a/tavern/internal/graphql/schema/ent.graphql b/tavern/internal/graphql/schema/ent.graphql index 0b67f9e6a..e111cdb63 100644 --- a/tavern/internal/graphql/schema/ent.graphql +++ b/tavern/internal/graphql/schema/ent.graphql @@ -299,6 +299,8 @@ type Host implements Node { tags: [Tag!] """Beacons that are present on this host system.""" beacons: [Beacon!] + """Processes reported as running on this host system.""" + processes: [Process!] } """Ordering options for Host connections""" input HostOrder { @@ -404,6 +406,9 @@ input HostWhereInput { """beacons edge predicates""" hasBeacons: Boolean hasBeaconsWith: [BeaconWhereInput!] + """processes edge predicates""" + hasProcesses: Boolean + hasProcessesWith: [ProcessWhereInput!] } """ An object with an ID. @@ -436,12 +441,34 @@ type PageInfo { } type Process implements Node { id: ID! + """Timestamp of when this ent was created""" + createdAt: Time! + """Timestamp of when this ent was last updated""" + lastModifiedAt: Time! """ID of the process.""" pid: Int! """The name of the process.""" name: String! """The user the process is running as.""" principal: String! + """Host the process was reported on.""" + host: Host! + """Task that reported this process.""" + task: Task! +} +"""Ordering options for Process connections""" +input ProcessOrder { + """The ordering direction.""" + direction: OrderDirection! = ASC + """The field by which to order Processes.""" + field: ProcessOrderField! +} +"""Properties by which Process connections can be ordered.""" +enum ProcessOrderField { + CREATED_AT + LAST_MODIFIED_AT + PROCESS_ID + NAME } """ ProcessWhereInput is used for filtering Process objects. @@ -460,6 +487,24 @@ input ProcessWhereInput { idGTE: ID idLT: ID idLTE: ID + """created_at field predicates""" + createdAt: Time + createdAtNEQ: Time + createdAtIn: [Time!] + createdAtNotIn: [Time!] + createdAtGT: Time + createdAtGTE: Time + createdAtLT: Time + createdAtLTE: Time + """last_modified_at field predicates""" + lastModifiedAt: Time + lastModifiedAtNEQ: Time + lastModifiedAtIn: [Time!] + lastModifiedAtNotIn: [Time!] + lastModifiedAtGT: Time + lastModifiedAtGTE: Time + lastModifiedAtLT: Time + lastModifiedAtLTE: Time """pid field predicates""" pid: Int pidNEQ: Int @@ -497,6 +542,12 @@ input ProcessWhereInput { principalHasSuffix: String principalEqualFold: String principalContainsFold: String + """host edge predicates""" + hasHost: Boolean + hasHostWith: [HostWhereInput!] + """task edge predicates""" + hasTask: Boolean + hasTaskWith: [TaskWhereInput!] } type Query { """Fetches an object given its ID.""" @@ -1006,6 +1057,9 @@ input UpdateHostInput { addBeaconIDs: [ID!] removeBeaconIDs: [ID!] clearBeacons: Boolean + addProcessIDs: [ID!] + removeProcessIDs: [ID!] + clearProcesses: Boolean } """ UpdateTagInput is used for update Tag object. diff --git a/tavern/internal/www/schema.graphql b/tavern/internal/www/schema.graphql index d51b3b058..9873e5171 100644 --- a/tavern/internal/www/schema.graphql +++ b/tavern/internal/www/schema.graphql @@ -304,6 +304,8 @@ type Host implements Node { tags: [Tag!] """Beacons that are present on this host system.""" beacons: [Beacon!] + """Processes reported as running on this host system.""" + processes: [Process!] } """Ordering options for Host connections""" input HostOrder { @@ -409,6 +411,9 @@ input HostWhereInput { """beacons edge predicates""" hasBeacons: Boolean hasBeaconsWith: [BeaconWhereInput!] + """processes edge predicates""" + hasProcesses: Boolean + hasProcessesWith: [ProcessWhereInput!] } """ An object with an ID. @@ -441,12 +446,34 @@ type PageInfo { } type Process implements Node { id: ID! + """Timestamp of when this ent was created""" + createdAt: Time! + """Timestamp of when this ent was last updated""" + lastModifiedAt: Time! """ID of the process.""" pid: Int! """The name of the process.""" name: String! """The user the process is running as.""" principal: String! + """Host the process was reported on.""" + host: Host! + """Task that reported this process.""" + task: Task! +} +"""Ordering options for Process connections""" +input ProcessOrder { + """The ordering direction.""" + direction: OrderDirection! = ASC + """The field by which to order Processes.""" + field: ProcessOrderField! +} +"""Properties by which Process connections can be ordered.""" +enum ProcessOrderField { + CREATED_AT + LAST_MODIFIED_AT + PROCESS_ID + NAME } """ ProcessWhereInput is used for filtering Process objects. @@ -465,6 +492,24 @@ input ProcessWhereInput { idGTE: ID idLT: ID idLTE: ID + """created_at field predicates""" + createdAt: Time + createdAtNEQ: Time + createdAtIn: [Time!] + createdAtNotIn: [Time!] + createdAtGT: Time + createdAtGTE: Time + createdAtLT: Time + createdAtLTE: Time + """last_modified_at field predicates""" + lastModifiedAt: Time + lastModifiedAtNEQ: Time + lastModifiedAtIn: [Time!] + lastModifiedAtNotIn: [Time!] + lastModifiedAtGT: Time + lastModifiedAtGTE: Time + lastModifiedAtLT: Time + lastModifiedAtLTE: Time """pid field predicates""" pid: Int pidNEQ: Int @@ -502,6 +547,12 @@ input ProcessWhereInput { principalHasSuffix: String principalEqualFold: String principalContainsFold: String + """host edge predicates""" + hasHost: Boolean + hasHostWith: [HostWhereInput!] + """task edge predicates""" + hasTask: Boolean + hasTaskWith: [TaskWhereInput!] } type Query { """Fetches an object given its ID.""" @@ -1011,6 +1062,9 @@ input UpdateHostInput { addBeaconIDs: [ID!] removeBeaconIDs: [ID!] clearBeacons: Boolean + addProcessIDs: [ID!] + removeProcessIDs: [ID!] + clearProcesses: Boolean } """ UpdateTagInput is used for update Tag object. From 7cf10dc9d086ec086b2c06d130402c7ea51f4c7b Mon Sep 17 00:00:00 2001 From: KCarretto Date: Tue, 23 Jan 2024 00:08:12 +0000 Subject: [PATCH 3/3] Generated c2 lib rust bindings --- implants/lib/c2/src/c2.rs | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/implants/lib/c2/src/c2.rs b/implants/lib/c2/src/c2.rs index 0d67ff5dc..c80ea3fe5 100644 --- a/implants/lib/c2/src/c2.rs +++ b/implants/lib/c2/src/c2.rs @@ -124,6 +124,17 @@ pub struct TaskOutput { #[prost(message, optional, tag = "5")] pub exec_finished_at: ::core::option::Option<::prost_types::Timestamp>, } +/// Process running on the system. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Process { + #[prost(uint64, tag = "1")] + pub pid: u64, + #[prost(string, tag = "2")] + pub name: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub principal: ::prost::alloc::string::String, +} /// /// RPC Messages #[allow(clippy::derive_partial_eq_without_eq)] @@ -159,6 +170,17 @@ pub struct DownloadFileResponse { #[prost(bytes = "vec", tag = "1")] pub chunk: ::prost::alloc::vec::Vec, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReportProcessListRequest { + #[prost(message, repeated, tag = "1")] + pub list: ::prost::alloc::vec::Vec, + #[prost(int64, tag = "2")] + pub task_id: i64, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReportProcessListResponse {} /// Generated client implementations. pub mod c2_client { #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] @@ -289,6 +311,31 @@ pub mod c2_client { self.inner.unary(req, path, codec).await } /// + /// Report the active list of running processes. This list will replace any previously reported + /// lists for the same host. + pub async fn report_process_list( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static("/c2.C2/ReportProcessList"); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new("c2.C2", "ReportProcessList")); + self.inner.unary(req, path, codec).await + } + /// /// Download a file from the server, returning one or more chunks of data. /// The maximum size of these chunks is determined by the server. /// The server should reply with two headers: