From 486e811784493373de60d3bc0873ed1525c3f96c Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Sat, 19 Oct 2024 13:57:03 +0900 Subject: [PATCH 1/7] Add projectId field to ExperimentRunDetailsPanel to retrieve experiment run Signed-off-by: DongYoung Kim --- chaoscenter/web/src/api/core/log/getPodLog.ts | 2 ++ .../web/src/controllers/CustomStepLog/CustomStepLog.tsx | 3 +++ chaoscenter/web/src/controllers/LogsTab/LogsTab.tsx | 1 + .../src/views/ExperimentRunDetails/ExperimentRunDetails.tsx | 1 + .../ExperimentRunDetailsPanel/ExperimentRunDetailsPanel.tsx | 5 +++++ .../web/src/views/ExperimentRunDetailsPanel/Tabs/LogsTab.tsx | 3 +++ 6 files changed, 15 insertions(+) diff --git a/chaoscenter/web/src/api/core/log/getPodLog.ts b/chaoscenter/web/src/api/core/log/getPodLog.ts index 3b6d05a1632..393b72abff4 100644 --- a/chaoscenter/web/src/api/core/log/getPodLog.ts +++ b/chaoscenter/web/src/api/core/log/getPodLog.ts @@ -14,6 +14,7 @@ interface GetPodLogsRequest { request: { // requestID: string; infraID: string; + projectID: string; experimentRunID?: string; podName: string; podNamespace: string; @@ -43,6 +44,7 @@ export function getPodLogsSubscription({ variables: { request: { infraID: request.infraID, + projectID: request.projectID, experimentRunID: request.experimentRunID, podName: request.podName, podNamespace: request.podNamespace, diff --git a/chaoscenter/web/src/controllers/CustomStepLog/CustomStepLog.tsx b/chaoscenter/web/src/controllers/CustomStepLog/CustomStepLog.tsx index 028b7daccc4..d5a5e7be05f 100644 --- a/chaoscenter/web/src/controllers/CustomStepLog/CustomStepLog.tsx +++ b/chaoscenter/web/src/controllers/CustomStepLog/CustomStepLog.tsx @@ -11,6 +11,7 @@ interface CustomStepLogControllerProps { namespace: string | undefined; workflowRunID: string | undefined; infraID: string | undefined; + projectID: string | undefined; podName: string; requestID: string; phase: ExperimentRunStatus | undefined; @@ -19,6 +20,7 @@ interface CustomStepLogControllerProps { export default function CustomStepLogController({ workflowRunID, infraID, + projectID, podName, chaosData, nodeType, @@ -36,6 +38,7 @@ export default function CustomStepLogController({ ...scope, infraID: infraID ?? '', // requestID: requestID, + projectID: projectID ?? '', experimentRunID: workflowRunID, podName: podName, podNamespace: namespace ?? '', diff --git a/chaoscenter/web/src/controllers/LogsTab/LogsTab.tsx b/chaoscenter/web/src/controllers/LogsTab/LogsTab.tsx index d06ba58f8e6..d46acddd5e3 100644 --- a/chaoscenter/web/src/controllers/LogsTab/LogsTab.tsx +++ b/chaoscenter/web/src/controllers/LogsTab/LogsTab.tsx @@ -7,6 +7,7 @@ interface LogsTabControllerProps { nodeType: string | undefined; chaosData: ChaosData | undefined; infraID: string | undefined; + projectID: string | undefined; workflowRunID: string | undefined; podID: string; experimentPod?: string; diff --git a/chaoscenter/web/src/views/ExperimentRunDetails/ExperimentRunDetails.tsx b/chaoscenter/web/src/views/ExperimentRunDetails/ExperimentRunDetails.tsx index 1cad30745e7..064e53d09b8 100644 --- a/chaoscenter/web/src/views/ExperimentRunDetails/ExperimentRunDetails.tsx +++ b/chaoscenter/web/src/views/ExperimentRunDetails/ExperimentRunDetails.tsx @@ -198,6 +198,7 @@ export default function ExperimentRunDetailsView({ namespace={experimentExecutionDetails?.namespace} probeData={probeData} infraID={infra?.infraID} + projectID={scope.projectID} setSelectedNodeID={setSelectedNodeID} experimentRunID={experimentRunID} podID={selectedNodeID} diff --git a/chaoscenter/web/src/views/ExperimentRunDetailsPanel/ExperimentRunDetailsPanel.tsx b/chaoscenter/web/src/views/ExperimentRunDetailsPanel/ExperimentRunDetailsPanel.tsx index 4372d9547fd..db0d956a02a 100644 --- a/chaoscenter/web/src/views/ExperimentRunDetailsPanel/ExperimentRunDetailsPanel.tsx +++ b/chaoscenter/web/src/views/ExperimentRunDetailsPanel/ExperimentRunDetailsPanel.tsx @@ -31,6 +31,7 @@ interface DetailsTabProps { probeData: ProbeInRuns[] | undefined; experimentRunID: string | undefined; infraID: string | undefined; + projectID: string | undefined; namespace: string | undefined; phase: ExperimentRunStatus | undefined; podID: string; @@ -44,6 +45,7 @@ const DetailsTabs = ({ phase, experimentRunID, infraID, + projectID, podID, manifest, probeData, @@ -88,6 +90,7 @@ const DetailsTabs = ({ phase={phase} workflowRunID={experimentRunID} infraID={infraID} + projectID={projectID} podID={podID} /> ) @@ -110,6 +113,7 @@ const ExperimentRunDetailsPanel = ({ phase, namespace, infraID, + projectID, probeData, podID, manifest, @@ -261,6 +265,7 @@ const ExperimentRunDetailsPanel = ({ probeData={probeData} experimentRunID={experimentRunID} infraID={infraID} + projectID={projectID} loading={loading} phase={phase} namespace={namespace} diff --git a/chaoscenter/web/src/views/ExperimentRunDetailsPanel/Tabs/LogsTab.tsx b/chaoscenter/web/src/views/ExperimentRunDetailsPanel/Tabs/LogsTab.tsx index 0c6be1d24bf..ecd86e0f681 100644 --- a/chaoscenter/web/src/views/ExperimentRunDetailsPanel/Tabs/LogsTab.tsx +++ b/chaoscenter/web/src/views/ExperimentRunDetailsPanel/Tabs/LogsTab.tsx @@ -10,6 +10,7 @@ interface LogsTabViewProps { nodeType: string | undefined; chaosData: ChaosData | undefined; infraID: string | undefined; + projectID: string | undefined; workflowRunID: string | undefined; podID: string; requestID: string; @@ -22,6 +23,7 @@ export default function LogsTabView({ nodeType, chaosData, infraID, + projectID, workflowRunID, podID, requestID, @@ -37,6 +39,7 @@ export default function LogsTabView({ nodeType={nodeType} namespace={namespace} infraID={infraID} + projectID={projectID} requestID={requestID} workflowRunID={workflowRunID} podName={podID} From 47a781d14642dac58fa3bc51fedc8f2f99da6147 Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Sat, 19 Oct 2024 15:34:34 +0900 Subject: [PATCH 2/7] Add ExperimentRun model and requset for get experimentRun phase Signed-off-by: DongYoung Kim --- .../subscriber/pkg/graphql/definations.go | 6 ++++ .../subscriber/pkg/graphql/operations.go | 31 +++++++++++++++++++ chaoscenter/subscriber/pkg/types/graphql.go | 13 ++++++++ 3 files changed, 50 insertions(+) create mode 100644 chaoscenter/subscriber/pkg/types/graphql.go diff --git a/chaoscenter/subscriber/pkg/graphql/definations.go b/chaoscenter/subscriber/pkg/graphql/definations.go index 81f7869ea52..a72ac4f1106 100644 --- a/chaoscenter/subscriber/pkg/graphql/definations.go +++ b/chaoscenter/subscriber/pkg/graphql/definations.go @@ -1,8 +1,14 @@ package graphql +import ( + "subscriber/pkg/types" +) + type SubscriberGql interface { SendRequest(server string, payload []byte) (string, error) MarshalGQLData(gqlData interface{}) (string, error) + SendExperimentRunRuquest(infraData map[string]string, podLog types.PodLogRequest) (types.ExperimentRunResponse, error) + GenerateExperimentRunPayload(cid, accessKey, version string, podLog types.PodLogRequest) ([]byte, error) } type subscriberGql struct { diff --git a/chaoscenter/subscriber/pkg/graphql/operations.go b/chaoscenter/subscriber/pkg/graphql/operations.go index b2ea6372454..50da9b90e3a 100644 --- a/chaoscenter/subscriber/pkg/graphql/operations.go +++ b/chaoscenter/subscriber/pkg/graphql/operations.go @@ -7,6 +7,7 @@ import ( "net/http" "strconv" "strings" + "subscriber/pkg/types" log "github.com/sirupsen/logrus" ) @@ -48,3 +49,33 @@ func (gql *subscriberGql) MarshalGQLData(gqlData interface{}) (string, error) { processed = strings.Replace(processed, `\"`, `\\\"`, -1) return processed, nil } + +// Get an experiment run on the GraphQL server +func (gql *subscriberGql) SendExperimentRunRuquest(infraData map[string]string, podLog types.PodLogRequest) (types.ExperimentRunResponse, error) { + + payload, _ := gql.GenerateExperimentRunPayload(infraData["INFRA_ID"], infraData["ACCESS_KEY"], infraData["VERSION"], podLog) + + body, err := gql.SendRequest(infraData["SERVER_ADDR"], payload) + if err != nil { + log.WithError(err).Print("Failed to send experiment run request") + } + + var respsone types.ExperimentRunResponse + err = json.Unmarshal([]byte(body), &respsone) + if err != nil { + log.WithError(err).WithField("data", string(body)).Fatal("Failed to parse ExperimentRun data") + } + + log.Print("Response from the server: ", body) + + return respsone, nil +} + +func (gql *subscriberGql) GenerateExperimentRunPayload(cid, accessKey, version string, podLog types.PodLogRequest) ([]byte, error) { + infraID := `{infraID: \"` + cid + `\", version: \"` + version + `\", accessKey: \"` + accessKey + `\"}` + query := `{ infraID: ` + infraID + `, experimentRunID:\"` + podLog.ExperimentRunID + `\", projectID: \"` + podLog.ProjectID + `\", notifyID: \"\"}` + + var payload = []byte(`{"query":"query { getExperimentRunPhase(request:` + query + `){phase}}"}`) + + return payload, nil +} diff --git a/chaoscenter/subscriber/pkg/types/graphql.go b/chaoscenter/subscriber/pkg/types/graphql.go new file mode 100644 index 00000000000..f5dd8fe85c7 --- /dev/null +++ b/chaoscenter/subscriber/pkg/types/graphql.go @@ -0,0 +1,13 @@ +package types + +type ExperimentRunResponse struct { + Data ExperimentRun `json:"data"` +} + +type ExperimentRun struct { + ExperimentRun Phase `json:"getExperimentRunPhase"` +} + +type Phase struct { + Phase string `json:"phase"` +} From 5b26424ea5a07a8055c0595feeb95207fd0ccf32 Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Sat, 19 Oct 2024 16:44:38 +0900 Subject: [PATCH 3/7] Refactor Changing the code flow in SendPodLogs Signed-off-by: DongYoung Kim --- chaoscenter/subscriber/pkg/k8s/defination.go | 4 +- chaoscenter/subscriber/pkg/k8s/log.go | 53 +++++++++++++------- chaoscenter/subscriber/pkg/types/log.go | 1 + 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/chaoscenter/subscriber/pkg/k8s/defination.go b/chaoscenter/subscriber/pkg/k8s/defination.go index 2adac87f32c..0e6f249ad15 100644 --- a/chaoscenter/subscriber/pkg/k8s/defination.go +++ b/chaoscenter/subscriber/pkg/k8s/defination.go @@ -15,9 +15,9 @@ import ( type SubscriberK8s interface { GetLogs(podName, namespace, container string) (string, error) - CreatePodLog(podLog types.PodLogRequest) (types.PodLog, error) + CreatePodLog(infraData map[string]string, podLog types.PodLogRequest) (types.PodLog, error) SendPodLogs(infraData map[string]string, podLog types.PodLogRequest) - GenerateLogPayload(cid, accessKey, version string, podLog types.PodLogRequest) ([]byte, error) + GenerateLogPayload(cid, accessKey, version, processed string, podLog types.PodLogRequest) ([]byte, error) GetKubernetesNamespaces(request types.KubeNamespaceRequest) ([]*types.KubeNamespace, error) GetKubernetesObjects(request types.KubeObjRequest) (*types.KubeObject, error) GetObjectDataByNamespace(namespace string, dynamicClient dynamic.Interface, resourceType schema.GroupVersionResource) ([]types.ObjectData, error) diff --git a/chaoscenter/subscriber/pkg/k8s/log.go b/chaoscenter/subscriber/pkg/k8s/log.go index 21545ac6636..cdd7bcb4ecd 100644 --- a/chaoscenter/subscriber/pkg/k8s/log.go +++ b/chaoscenter/subscriber/pkg/k8s/log.go @@ -53,13 +53,32 @@ func (k8s *k8sSubscriber) GetLogs(podName, namespace, container string) (string, } // create pod log for normal pods and chaos-engine pods -func (k8s *k8sSubscriber) CreatePodLog(podLog types.PodLogRequest) (types.PodLog, error) { +func (k8s *k8sSubscriber) CreatePodLog(infraData map[string]string, podLog types.PodLogRequest) (types.PodLog, error) { logDetails := types.PodLog{} mainLog, err := k8s.GetLogs(podLog.PodName, podLog.PodNamespace, "main") // try getting argo pod logs if err != nil { + + // fetch ExperimentRun Phase from graphql + experimentRun, _ := k8s.gqlSubscriberServer.SendExperimentRunRuquest(infraData, podLog) + + // Categorizing log messages by experiment phase + switch experimentRun.Data.ExperimentRun.Phase { + case "Completed": + logDetails.MainPod = "Experiment pod is deleted" + case "Stopped": + logDetails.MainPod = "stopped" + case "Running": + logDetails.MainPod = "Workflow Pod is initailzing" + case "Queue": + logDetails.MainPod = "Queue" + case "NA": + logDetails.MainPod = "NA" + default: + logDetails.MainPod = "Workflow Pod is initailzing" + } + logrus.Errorf("Failed to get argo pod %v logs, err: %v", podLog.PodName, err) - logDetails.MainPod = "Failed to get argo pod logs" } else { logDetails.MainPod = strconv.Quote(strings.Replace(mainLog, `"`, `'`, -1)) logDetails.MainPod = logDetails.MainPod[1 : len(logDetails.MainPod)-1] @@ -96,11 +115,21 @@ func (k8s *k8sSubscriber) CreatePodLog(podLog types.PodLogRequest) (types.PodLog // SendPodLogs generates graphql mutation to send events updates to graphql server func (k8s *k8sSubscriber) SendPodLogs(infraData map[string]string, podLog types.PodLogRequest) { - // generate graphql payload - payload, err := k8s.GenerateLogPayload(infraData["INFRA_ID"], infraData["ACCESS_KEY"], infraData["VERSION"], podLog) + + logDetails, err := k8s.CreatePodLog(infraData, podLog) + if err != nil { + logrus.WithError(err).Print("failed to create pod logs") + } + + // MarashalGQLData + processed, err := k8s.gqlSubscriberServer.MarshalGQLData(logDetails) if err != nil { - logrus.WithError(err).Print("Error while retrieving the workflow logs") + processed = " Could not get logs " } + + // generate graphql payload + payload, _ := k8s.GenerateLogPayload(infraData["INFRA_ID"], infraData["ACCESS_KEY"], infraData["VERSION"], processed, podLog) + body, err := k8s.gqlSubscriberServer.SendRequest(infraData["SERVER_ADDR"], payload) if err != nil { logrus.Print(err.Error()) @@ -108,20 +137,8 @@ func (k8s *k8sSubscriber) SendPodLogs(infraData map[string]string, podLog types. logrus.Print("Response from the server: ", body) } -func (k8s *k8sSubscriber) GenerateLogPayload(cid, accessKey, version string, podLog types.PodLogRequest) ([]byte, error) { +func (k8s *k8sSubscriber) GenerateLogPayload(cid, accessKey, version, processed string, podLog types.PodLogRequest) ([]byte, error) { infraID := `{infraID: \"` + cid + `\", version: \"` + version + `\", accessKey: \"` + accessKey + `\"}` - processed := " Could not get logs " - - // get the logs - logDetails, err := k8s.CreatePodLog(podLog) - if err == nil { - // process log data - processed, err = k8s.gqlSubscriberServer.MarshalGQLData(logDetails) - if err != nil { - processed = " Could not get logs " - } - } - mutation := `{ infraID: ` + infraID + `, requestID:\"` + podLog.RequestID + `\", experimentRunID: \"` + podLog.ExperimentRunID + `\", podName: \"` + podLog.PodName + `\", podType: \"` + podLog.PodType + `\", log:\"` + processed[1:len(processed)-1] + `\"}` var payload = []byte(`{"query":"mutation { podLog(request:` + mutation + ` )}"}`) diff --git a/chaoscenter/subscriber/pkg/types/log.go b/chaoscenter/subscriber/pkg/types/log.go index 41553a116bf..9bd5ce0d55d 100644 --- a/chaoscenter/subscriber/pkg/types/log.go +++ b/chaoscenter/subscriber/pkg/types/log.go @@ -2,6 +2,7 @@ package types type PodLogRequest struct { RequestID string `json:"requestID"` + ProjectID string `json:"projectID"` InfraID string `json:"infraID"` ExperimentRunID string `json:"experimentRunID"` PodName string `json:"podName"` From 6bea966b7c27d707779aeac0b557ca64597aa7b6 Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Sat, 19 Oct 2024 16:48:25 +0900 Subject: [PATCH 4/7] Add request model and GetExperimentRunPhase resolver in experimentRunResolver Signed-off-by: DongYoung Kim --- .../shared/chaos_experiment.graphqls | 21 ++ .../shared/chaos_experiment_run.graphqls | 1 + .../shared/chaos_infrastructure.graphqls | 4 + .../graph/chaos_experiment_run.resolvers.go | 17 ++ .../server/graph/generated/generated.go | 245 +++++++++++++++++- .../graphql/server/graph/model/models_gen.go | 13 +- 6 files changed, 299 insertions(+), 2 deletions(-) diff --git a/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls b/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls index b6003ab121b..74ac071363b 100644 --- a/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls +++ b/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls @@ -326,6 +326,27 @@ type Weightages { weightage: Int! } + +input ExperimentRunPhaseRequest { + projectID: ID! + + """ + ID of the infra infra in which the experiment is running + """ + infraID: InfraIdentity! + + """ + ID of the experiment run which is to be queried + """ + experimentRunID: String! + + """ + notifyID is required to give an ack for non cron experiment execution + """ + notifyID: String +} + + """ Defines the details of a experiment run """ diff --git a/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls b/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls index 15ea5f9bd3e..8e9c3ecb9d9 100644 --- a/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls +++ b/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls @@ -16,6 +16,7 @@ extend type Query { Query to get experiment run stats """ getExperimentRunStats(projectID: ID!): GetExperimentRunStatsResponse! + getExperimentRunPhase(request: ExperimentRunPhaseRequest!): ExperimentRun! } extend type Mutation { diff --git a/chaoscenter/graphql/definitions/shared/chaos_infrastructure.graphqls b/chaoscenter/graphql/definitions/shared/chaos_infrastructure.graphqls index 467a6a2da76..702372a3ac3 100644 --- a/chaoscenter/graphql/definitions/shared/chaos_infrastructure.graphqls +++ b/chaoscenter/graphql/definitions/shared/chaos_infrastructure.graphqls @@ -288,6 +288,10 @@ input PodLogRequest { """ infraID: ID! """ + + """ + projectID: ID! + """ ID of a experiment run """ experimentRunID: ID! diff --git a/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go b/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go index 35ab1e8994d..551e6128ff0 100644 --- a/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go +++ b/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go @@ -146,3 +146,20 @@ func (r *queryResolver) GetExperimentRunStats(ctx context.Context, projectID str } return uiResponse, err } + +// GetExperimentRunPhase is the resolver for the getExperimentRunPhase field. +func (r *queryResolver) GetExperimentRunPhase(ctx context.Context, request model.ExperimentRunPhaseRequest) (*model.ExperimentRun, error) { + _, err := r.chaosInfrastructureService.VerifyInfra(*request.InfraID) + + if err != nil { + logrus.Error("Validation failed : ", request.InfraID) + return nil, err + } + + expRunResponse, err := r.chaosExperimentRunHandler.GetExperimentRun(ctx, request.ProjectID, &request.ExperimentRunID, request.NotifyID) + if err != nil { + logrus.Error("failed to get chaosExpeirmentRun: ", err) + return nil, err + } + return expRunResponse, err +} diff --git a/chaoscenter/graphql/server/graph/generated/generated.go b/chaoscenter/graphql/server/graph/generated/generated.go index 9f53f4eaaca..f5085a222e2 100644 --- a/chaoscenter/graphql/server/graph/generated/generated.go +++ b/chaoscenter/graphql/server/graph/generated/generated.go @@ -608,6 +608,7 @@ type ComplexityRoot struct { GetEnvironment func(childComplexity int, projectID string, environmentID string) int GetExperiment func(childComplexity int, projectID string, experimentID string) int GetExperimentRun func(childComplexity int, projectID string, experimentRunID *string, notifyID *string) int + GetExperimentRunPhase func(childComplexity int, request model.ExperimentRunPhaseRequest) int GetExperimentRunStats func(childComplexity int, projectID string) int GetExperimentStats func(childComplexity int, projectID string) int GetGitOpsDetails func(childComplexity int, projectID string) int @@ -769,6 +770,7 @@ type QueryResolver interface { GetExperimentRun(ctx context.Context, projectID string, experimentRunID *string, notifyID *string) (*model.ExperimentRun, error) ListExperimentRun(ctx context.Context, projectID string, request model.ListExperimentRunRequest) (*model.ListExperimentRunResponse, error) GetExperimentRunStats(ctx context.Context, projectID string) (*model.GetExperimentRunStatsResponse, error) + GetExperimentRunPhase(ctx context.Context, request model.ExperimentRunPhaseRequest) (*model.ExperimentRun, error) GetInfra(ctx context.Context, projectID string, infraID string) (*model.Infra, error) ListInfras(ctx context.Context, projectID string, request *model.ListInfraRequest) (*model.ListInfraResponse, error) GetInfraDetails(ctx context.Context, infraID string, projectID string) (*model.Infra, error) @@ -3731,6 +3733,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.GetExperimentRun(childComplexity, args["projectID"].(string), args["experimentRunID"].(*string), args["notifyID"].(*string)), true + case "Query.getExperimentRunPhase": + if e.complexity.Query.GetExperimentRunPhase == nil { + break + } + + args, err := ec.field_Query_getExperimentRunPhase_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.GetExperimentRunPhase(childComplexity, args["request"].(model.ExperimentRunPhaseRequest)), true + case "Query.getExperimentRunStats": if e.complexity.Query.GetExperimentRunStats == nil { break @@ -4423,6 +4437,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputExperimentFilterInput, ec.unmarshalInputExperimentRequest, ec.unmarshalInputExperimentRunFilterInput, + ec.unmarshalInputExperimentRunPhaseRequest, ec.unmarshalInputExperimentRunRequest, ec.unmarshalInputExperimentRunSortInput, ec.unmarshalInputExperimentSortInput, @@ -4904,6 +4919,27 @@ type Weightages { weightage: Int! } + +input ExperimentRunPhaseRequest { + projectID: ID! + + """ + ID of the infra infra in which the experiment is running + """ + infraID: InfraIdentity! + + """ + ID of the experiment run which is to be queried + """ + experimentRunID: String! + + """ + notifyID is required to give an ack for non cron experiment execution + """ + notifyID: String +} + + """ Defines the details of a experiment run """ @@ -5376,6 +5412,7 @@ type Mutation { Query to get experiment run stats """ getExperimentRunStats(projectID: ID!): GetExperimentRunStatsResponse! + getExperimentRunPhase(request: ExperimentRunPhaseRequest!): ExperimentRun! } extend type Mutation { @@ -5688,6 +5725,10 @@ input PodLogRequest { """ infraID: ID! """ + + """ + projectID: ID! + """ ID of a experiment run """ experimentRunID: ID! @@ -9272,6 +9313,21 @@ func (ec *executionContext) field_Query_getEnvironment_args(ctx context.Context, return args, nil } +func (ec *executionContext) field_Query_getExperimentRunPhase_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.ExperimentRunPhaseRequest + if tmp, ok := rawArgs["request"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("request")) + arg0, err = ec.unmarshalNExperimentRunPhaseRequest2githubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRunPhaseRequest(ctx, tmp) + if err != nil { + return nil, err + } + } + args["request"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_getExperimentRunStats_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -28843,6 +28899,111 @@ func (ec *executionContext) fieldContext_Query_getExperimentRunStats(ctx context return fc, nil } +func (ec *executionContext) _Query_getExperimentRunPhase(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_getExperimentRunPhase(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.Query().GetExperimentRunPhase(rctx, fc.Args["request"].(model.ExperimentRunPhaseRequest)) + }) + 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.(*model.ExperimentRun) + fc.Result = res + return ec.marshalNExperimentRun2ᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRun(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_getExperimentRunPhase(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "projectID": + return ec.fieldContext_ExperimentRun_projectID(ctx, field) + case "experimentRunID": + return ec.fieldContext_ExperimentRun_experimentRunID(ctx, field) + case "experimentType": + return ec.fieldContext_ExperimentRun_experimentType(ctx, field) + case "experimentID": + return ec.fieldContext_ExperimentRun_experimentID(ctx, field) + case "weightages": + return ec.fieldContext_ExperimentRun_weightages(ctx, field) + case "updatedAt": + return ec.fieldContext_ExperimentRun_updatedAt(ctx, field) + case "createdAt": + return ec.fieldContext_ExperimentRun_createdAt(ctx, field) + case "infra": + return ec.fieldContext_ExperimentRun_infra(ctx, field) + case "experimentName": + return ec.fieldContext_ExperimentRun_experimentName(ctx, field) + case "experimentManifest": + return ec.fieldContext_ExperimentRun_experimentManifest(ctx, field) + case "phase": + return ec.fieldContext_ExperimentRun_phase(ctx, field) + case "resiliencyScore": + return ec.fieldContext_ExperimentRun_resiliencyScore(ctx, field) + case "faultsPassed": + return ec.fieldContext_ExperimentRun_faultsPassed(ctx, field) + case "faultsFailed": + return ec.fieldContext_ExperimentRun_faultsFailed(ctx, field) + case "faultsAwaited": + return ec.fieldContext_ExperimentRun_faultsAwaited(ctx, field) + case "faultsStopped": + return ec.fieldContext_ExperimentRun_faultsStopped(ctx, field) + case "faultsNa": + return ec.fieldContext_ExperimentRun_faultsNa(ctx, field) + case "totalFaults": + return ec.fieldContext_ExperimentRun_totalFaults(ctx, field) + case "executionData": + return ec.fieldContext_ExperimentRun_executionData(ctx, field) + case "isRemoved": + return ec.fieldContext_ExperimentRun_isRemoved(ctx, field) + case "updatedBy": + return ec.fieldContext_ExperimentRun_updatedBy(ctx, field) + case "createdBy": + return ec.fieldContext_ExperimentRun_createdBy(ctx, field) + case "notifyID": + return ec.fieldContext_ExperimentRun_notifyID(ctx, field) + case "runSequence": + return ec.fieldContext_ExperimentRun_runSequence(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExperimentRun", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_getExperimentRunPhase_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Query_getInfra(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_getInfra(ctx, field) if err != nil { @@ -36363,6 +36524,54 @@ func (ec *executionContext) unmarshalInputExperimentRunFilterInput(ctx context.C return it, nil } +func (ec *executionContext) unmarshalInputExperimentRunPhaseRequest(ctx context.Context, obj interface{}) (model.ExperimentRunPhaseRequest, error) { + var it model.ExperimentRunPhaseRequest + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"projectID", "infraID", "experimentRunID", "notifyID"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "projectID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ProjectID = data + case "infraID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("infraID")) + data, err := ec.unmarshalNInfraIdentity2ᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐInfraIdentity(ctx, v) + if err != nil { + return it, err + } + it.InfraID = data + case "experimentRunID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("experimentRunID")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.ExperimentRunID = data + case "notifyID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notifyID")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.NotifyID = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputExperimentRunRequest(ctx context.Context, obj interface{}) (model.ExperimentRunRequest, error) { var it model.ExperimentRunRequest asMap := map[string]interface{}{} @@ -38042,7 +38251,7 @@ func (ec *executionContext) unmarshalInputPodLogRequest(ctx context.Context, obj asMap[k] = v } - fieldsInOrder := [...]string{"infraID", "experimentRunID", "podName", "podNamespace", "podType", "expPod", "runnerPod", "chaosNamespace"} + fieldsInOrder := [...]string{"infraID", "projectID", "experimentRunID", "podName", "podNamespace", "podType", "expPod", "runnerPod", "chaosNamespace"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -38056,6 +38265,13 @@ func (ec *executionContext) unmarshalInputPodLogRequest(ctx context.Context, obj return it, err } it.InfraID = data + case "projectID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.ProjectID = data case "experimentRunID": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("experimentRunID")) data, err := ec.unmarshalNID2string(ctx, v) @@ -42577,6 +42793,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "getExperimentRunPhase": + 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._Query_getExperimentRunPhase(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "getInfra": field := field @@ -44528,6 +44766,11 @@ func (ec *executionContext) marshalNExperimentRun2ᚖgithubᚗcomᚋlitmuschaos return ec._ExperimentRun(ctx, sel, v) } +func (ec *executionContext) unmarshalNExperimentRunPhaseRequest2githubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRunPhaseRequest(ctx context.Context, v interface{}) (model.ExperimentRunPhaseRequest, error) { + res, err := ec.unmarshalInputExperimentRunPhaseRequest(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNExperimentRunRequest2githubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRunRequest(ctx context.Context, v interface{}) (model.ExperimentRunRequest, error) { res, err := ec.unmarshalInputExperimentRunRequest(ctx, v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/chaoscenter/graphql/server/graph/model/models_gen.go b/chaoscenter/graphql/server/graph/model/models_gen.go index 9734945dfb1..217dc72e667 100644 --- a/chaoscenter/graphql/server/graph/model/models_gen.go +++ b/chaoscenter/graphql/server/graph/model/models_gen.go @@ -646,6 +646,16 @@ type ExperimentRunFilterInput struct { InfraTypes []*InfrastructureType `json:"infraTypes,omitempty"` } +type ExperimentRunPhaseRequest struct { + ProjectID string `json:"projectID"` + // ID of the infra infra in which the experiment is running + InfraID *InfraIdentity `json:"infraID"` + // ID of the experiment run which is to be queried + ExperimentRunID string `json:"experimentRunID"` + // notifyID is required to give an ack for non cron experiment execution + NotifyID *string `json:"notifyID,omitempty"` +} + // Defines the details for a experiment run type ExperimentRunRequest struct { // ID of the experiment @@ -1663,7 +1673,8 @@ type PodLog struct { // Defines the details for fetching the pod logs type PodLogRequest struct { // ID of the cluster - InfraID string `json:"infraID"` + InfraID string `json:"infraID"` + ProjectID string `json:"projectID"` // ID of a experiment run ExperimentRunID string `json:"experimentRunID"` // Name of the pod for which logs are required From 6848952e1a594b08b0430d6bcf5b3c9d8c7601a2 Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Sat, 19 Oct 2024 19:59:29 +0900 Subject: [PATCH 5/7] Refactor getPodLogs to improve code clarity Signed-off-by: DongYoung Kim --- chaoscenter/subscriber/pkg/k8s/defination.go | 4 +- chaoscenter/subscriber/pkg/k8s/log.go | 83 ++++++++++++-------- 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/chaoscenter/subscriber/pkg/k8s/defination.go b/chaoscenter/subscriber/pkg/k8s/defination.go index 0e6f249ad15..24f658d424d 100644 --- a/chaoscenter/subscriber/pkg/k8s/defination.go +++ b/chaoscenter/subscriber/pkg/k8s/defination.go @@ -15,7 +15,9 @@ import ( type SubscriberK8s interface { GetLogs(podName, namespace, container string) (string, error) - CreatePodLog(infraData map[string]string, podLog types.PodLogRequest) (types.PodLog, error) + GetPodLogs(infraData map[string]string, podLog types.PodLogRequest) (types.PodLog, error) + categorizeLogByPhase(phase string) string + CreatePodLog(infraData map[string]string, logDetails types.PodLog, podLog types.PodLogRequest) (types.PodLog, error) SendPodLogs(infraData map[string]string, podLog types.PodLogRequest) GenerateLogPayload(cid, accessKey, version, processed string, podLog types.PodLogRequest) ([]byte, error) GetKubernetesNamespaces(request types.KubeNamespaceRequest) ([]*types.KubeNamespace, error) diff --git a/chaoscenter/subscriber/pkg/k8s/log.go b/chaoscenter/subscriber/pkg/k8s/log.go index cdd7bcb4ecd..cefa1be432a 100644 --- a/chaoscenter/subscriber/pkg/k8s/log.go +++ b/chaoscenter/subscriber/pkg/k8s/log.go @@ -53,36 +53,7 @@ func (k8s *k8sSubscriber) GetLogs(podName, namespace, container string) (string, } // create pod log for normal pods and chaos-engine pods -func (k8s *k8sSubscriber) CreatePodLog(infraData map[string]string, podLog types.PodLogRequest) (types.PodLog, error) { - logDetails := types.PodLog{} - mainLog, err := k8s.GetLogs(podLog.PodName, podLog.PodNamespace, "main") - // try getting argo pod logs - if err != nil { - - // fetch ExperimentRun Phase from graphql - experimentRun, _ := k8s.gqlSubscriberServer.SendExperimentRunRuquest(infraData, podLog) - - // Categorizing log messages by experiment phase - switch experimentRun.Data.ExperimentRun.Phase { - case "Completed": - logDetails.MainPod = "Experiment pod is deleted" - case "Stopped": - logDetails.MainPod = "stopped" - case "Running": - logDetails.MainPod = "Workflow Pod is initailzing" - case "Queue": - logDetails.MainPod = "Queue" - case "NA": - logDetails.MainPod = "NA" - default: - logDetails.MainPod = "Workflow Pod is initailzing" - } - - logrus.Errorf("Failed to get argo pod %v logs, err: %v", podLog.PodName, err) - } else { - logDetails.MainPod = strconv.Quote(strings.Replace(mainLog, `"`, `'`, -1)) - logDetails.MainPod = logDetails.MainPod[1 : len(logDetails.MainPod)-1] - } +func (k8s *k8sSubscriber) CreatePodLog(infraData map[string]string, logDetails types.PodLog, podLog types.PodLogRequest) (types.PodLog, error) { // try getting experiment pod logs if requested if strings.ToLower(podLog.PodType) == "chaosengine" && podLog.ChaosNamespace != nil { chaosLog := make(map[string]string) @@ -116,9 +87,9 @@ func (k8s *k8sSubscriber) CreatePodLog(infraData map[string]string, podLog types // SendPodLogs generates graphql mutation to send events updates to graphql server func (k8s *k8sSubscriber) SendPodLogs(infraData map[string]string, podLog types.PodLogRequest) { - logDetails, err := k8s.CreatePodLog(infraData, podLog) + logDetails, err := k8s.GetPodLogs(infraData, podLog) if err != nil { - logrus.WithError(err).Print("failed to create pod logs") + logrus.WithError(err).Print("failed to get pod logs") } // MarashalGQLData @@ -127,7 +98,7 @@ func (k8s *k8sSubscriber) SendPodLogs(infraData map[string]string, podLog types. processed = " Could not get logs " } - // generate graphql payload + // Generate graphql payload payload, _ := k8s.GenerateLogPayload(infraData["INFRA_ID"], infraData["ACCESS_KEY"], infraData["VERSION"], processed, podLog) body, err := k8s.gqlSubscriberServer.SendRequest(infraData["SERVER_ADDR"], payload) @@ -137,6 +108,52 @@ func (k8s *k8sSubscriber) SendPodLogs(infraData map[string]string, podLog types. logrus.Print("Response from the server: ", body) } +func (k8s *k8sSubscriber) GetPodLogs(infraData map[string]string, podLog types.PodLogRequest) (types.PodLog, error) { + logDetails := types.PodLog{} + mainLog, err := k8s.GetLogs(podLog.PodName, podLog.PodNamespace, "main") + + // try getting argo pod logs + if err != nil { + + // fetch ExperimentRun Phase from graphql + experimentRun, _ := k8s.gqlSubscriberServer.SendExperimentRunRuquest(infraData, podLog) + logDetails.MainPod = k8s.categorizeLogByPhase(experimentRun.Data.ExperimentRun.Phase) + + logrus.WithError(err).Print("Failed to get pod logs for attempting to fetch experiment run phase") + + } else { + + logDetails.MainPod = strconv.Quote(strings.Replace(mainLog, `"`, `'`, -1)) + logDetails.MainPod = logDetails.MainPod[1 : len(logDetails.MainPod)-1] + + logDetails, err = k8s.CreatePodLog(infraData, logDetails, podLog) + + if err != nil { + return logDetails, err + } + } + + return logDetails, nil +} + +// Categorizing log messages by experiment phase +func (k8s *k8sSubscriber) categorizeLogByPhase(phase string) string { + switch phase { + case "Completed": + return "Experiment pod is deleted" + case "Stopped": + return "Stopped" + case "Running": + return "Workflow Pod is initializing" + case "Queue": + return "Queue" + case "NA": + return "NA" + default: + return "Workflow Pod is initializing" + } +} + func (k8s *k8sSubscriber) GenerateLogPayload(cid, accessKey, version, processed string, podLog types.PodLogRequest) ([]byte, error) { infraID := `{infraID: \"` + cid + `\", version: \"` + version + `\", accessKey: \"` + accessKey + `\"}` mutation := `{ infraID: ` + infraID + `, requestID:\"` + podLog.RequestID + `\", experimentRunID: \"` + podLog.ExperimentRunID + `\", podName: \"` + podLog.PodName + `\", podType: \"` + podLog.PodType + `\", log:\"` + processed[1:len(processed)-1] + `\"}` From a89193a925d3100609ed438507a0e894057b4573 Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Sat, 19 Oct 2024 23:45:54 +0900 Subject: [PATCH 6/7] Add experiment phase case Signed-off-by: DongYoung Kim --- chaoscenter/subscriber/pkg/k8s/log.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/chaoscenter/subscriber/pkg/k8s/log.go b/chaoscenter/subscriber/pkg/k8s/log.go index cefa1be432a..015574f07af 100644 --- a/chaoscenter/subscriber/pkg/k8s/log.go +++ b/chaoscenter/subscriber/pkg/k8s/log.go @@ -149,6 +149,14 @@ func (k8s *k8sSubscriber) categorizeLogByPhase(phase string) string { return "Queue" case "NA": return "NA" + case "Terminated": + return "Terminated" + case "Completed_With_Error": + return "Completed_With_Error" + case "Timeout": + return "Timeout" + case "Error": + return "it can't run experiment" default: return "Workflow Pod is initializing" } From 53a51e1b7430236f8f751395c75a6550fdc0d600 Mon Sep 17 00:00:00 2001 From: DongYoung Kim Date: Fri, 13 Dec 2024 18:36:44 +0900 Subject: [PATCH 7/7] feat: update log message and graphql schema Signed-off-by: DongYoung Kim --- .../shared/chaos_experiment.graphqls | 21 -- .../shared/chaos_experiment_run.graphqls | 3 +- .../graph/chaos_experiment_run.resolvers.go | 45 ++- .../server/graph/generated/generated.go | 259 ++---------------- .../graphql/server/graph/model/models_gen.go | 10 - .../subscriber/pkg/graphql/operations.go | 7 +- chaoscenter/subscriber/pkg/k8s/log.go | 22 +- chaoscenter/subscriber/pkg/types/graphql.go | 2 +- 8 files changed, 60 insertions(+), 309 deletions(-) diff --git a/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls b/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls index 74ac071363b..b6003ab121b 100644 --- a/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls +++ b/chaoscenter/graphql/definitions/shared/chaos_experiment.graphqls @@ -326,27 +326,6 @@ type Weightages { weightage: Int! } - -input ExperimentRunPhaseRequest { - projectID: ID! - - """ - ID of the infra infra in which the experiment is running - """ - infraID: InfraIdentity! - - """ - ID of the experiment run which is to be queried - """ - experimentRunID: String! - - """ - notifyID is required to give an ack for non cron experiment execution - """ - notifyID: String -} - - """ Defines the details of a experiment run """ diff --git a/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls b/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls index 8e9c3ecb9d9..fb095210317 100644 --- a/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls +++ b/chaoscenter/graphql/definitions/shared/chaos_experiment_run.graphqls @@ -2,7 +2,7 @@ extend type Query { """ Returns experiment run based on experiment run ID """ - getExperimentRun(projectID: ID!, experimentRunID: ID, notifyID: ID): ExperimentRun! + getExperimentRun(projectID: ID!, experimentRunID: ID, notifyID: ID, infraID: InfraIdentity): ExperimentRun! """ Returns the list of experiment run based on various filter parameters @@ -16,7 +16,6 @@ extend type Query { Query to get experiment run stats """ getExperimentRunStats(projectID: ID!): GetExperimentRunStatsResponse! - getExperimentRunPhase(request: ExperimentRunPhaseRequest!): ExperimentRun! } extend type Mutation { diff --git a/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go b/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go index 551e6128ff0..e54a59f08e7 100644 --- a/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go +++ b/chaoscenter/graphql/server/graph/chaos_experiment_run.resolvers.go @@ -82,17 +82,33 @@ func (r *mutationResolver) StopExperimentRuns(ctx context.Context, projectID str } // GetExperimentRun is the resolver for the getExperimentRun field. -func (r *queryResolver) GetExperimentRun(ctx context.Context, projectID string, experimentRunID *string, notifyID *string) (*model.ExperimentRun, error) { +func (r *queryResolver) GetExperimentRun(ctx context.Context, projectID string, experimentRunID *string, notifyID *string, infraID *model.InfraIdentity) (*model.ExperimentRun, error) { logFields := logrus.Fields{ "projectId": projectID, "chaosExperimentRunId": experimentRunID, + "infraID": infraID, } + logrus.WithFields(logFields).Info("request received to fetch chaos experiment run") - err := authorization.ValidateRole(ctx, projectID, - authorization.MutationRbacRules[authorization.GetWorkflowRun], - model.InvitationAccepted.String()) - if err != nil { - return nil, err + + // Infrastructure validation + if infraID != nil { + _, err := r.chaosInfrastructureService.VerifyInfra(*infraID) + + if err != nil { + logrus.WithFields(logFields).Error(err) + return nil, err + } + + // Authorization validation + } else { + err := authorization.ValidateRole(ctx, projectID, + authorization.MutationRbacRules[authorization.GetWorkflowRun], + model.InvitationAccepted.String()) + + if err != nil { + return nil, err + } } expRunResponse, err := r.chaosExperimentRunHandler.GetExperimentRun(ctx, projectID, experimentRunID, notifyID) @@ -146,20 +162,3 @@ func (r *queryResolver) GetExperimentRunStats(ctx context.Context, projectID str } return uiResponse, err } - -// GetExperimentRunPhase is the resolver for the getExperimentRunPhase field. -func (r *queryResolver) GetExperimentRunPhase(ctx context.Context, request model.ExperimentRunPhaseRequest) (*model.ExperimentRun, error) { - _, err := r.chaosInfrastructureService.VerifyInfra(*request.InfraID) - - if err != nil { - logrus.Error("Validation failed : ", request.InfraID) - return nil, err - } - - expRunResponse, err := r.chaosExperimentRunHandler.GetExperimentRun(ctx, request.ProjectID, &request.ExperimentRunID, request.NotifyID) - if err != nil { - logrus.Error("failed to get chaosExpeirmentRun: ", err) - return nil, err - } - return expRunResponse, err -} diff --git a/chaoscenter/graphql/server/graph/generated/generated.go b/chaoscenter/graphql/server/graph/generated/generated.go index f5085a222e2..e6adeece438 100644 --- a/chaoscenter/graphql/server/graph/generated/generated.go +++ b/chaoscenter/graphql/server/graph/generated/generated.go @@ -607,8 +607,7 @@ type ComplexityRoot struct { GetChaosHubStats func(childComplexity int, projectID string) int GetEnvironment func(childComplexity int, projectID string, environmentID string) int GetExperiment func(childComplexity int, projectID string, experimentID string) int - GetExperimentRun func(childComplexity int, projectID string, experimentRunID *string, notifyID *string) int - GetExperimentRunPhase func(childComplexity int, request model.ExperimentRunPhaseRequest) int + GetExperimentRun func(childComplexity int, projectID string, experimentRunID *string, notifyID *string, infraID *model.InfraIdentity) int GetExperimentRunStats func(childComplexity int, projectID string) int GetExperimentStats func(childComplexity int, projectID string) int GetGitOpsDetails func(childComplexity int, projectID string) int @@ -767,10 +766,9 @@ type QueryResolver interface { GetExperiment(ctx context.Context, projectID string, experimentID string) (*model.GetExperimentResponse, error) ListExperiment(ctx context.Context, projectID string, request model.ListExperimentRequest) (*model.ListExperimentResponse, error) GetExperimentStats(ctx context.Context, projectID string) (*model.GetExperimentStatsResponse, error) - GetExperimentRun(ctx context.Context, projectID string, experimentRunID *string, notifyID *string) (*model.ExperimentRun, error) + GetExperimentRun(ctx context.Context, projectID string, experimentRunID *string, notifyID *string, infraID *model.InfraIdentity) (*model.ExperimentRun, error) ListExperimentRun(ctx context.Context, projectID string, request model.ListExperimentRunRequest) (*model.ListExperimentRunResponse, error) GetExperimentRunStats(ctx context.Context, projectID string) (*model.GetExperimentRunStatsResponse, error) - GetExperimentRunPhase(ctx context.Context, request model.ExperimentRunPhaseRequest) (*model.ExperimentRun, error) GetInfra(ctx context.Context, projectID string, infraID string) (*model.Infra, error) ListInfras(ctx context.Context, projectID string, request *model.ListInfraRequest) (*model.ListInfraResponse, error) GetInfraDetails(ctx context.Context, infraID string, projectID string) (*model.Infra, error) @@ -3731,19 +3729,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.GetExperimentRun(childComplexity, args["projectID"].(string), args["experimentRunID"].(*string), args["notifyID"].(*string)), true - - case "Query.getExperimentRunPhase": - if e.complexity.Query.GetExperimentRunPhase == nil { - break - } - - args, err := ec.field_Query_getExperimentRunPhase_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.GetExperimentRunPhase(childComplexity, args["request"].(model.ExperimentRunPhaseRequest)), true + return e.complexity.Query.GetExperimentRun(childComplexity, args["projectID"].(string), args["experimentRunID"].(*string), args["notifyID"].(*string), args["infraID"].(*model.InfraIdentity)), true case "Query.getExperimentRunStats": if e.complexity.Query.GetExperimentRunStats == nil { @@ -4437,7 +4423,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputExperimentFilterInput, ec.unmarshalInputExperimentRequest, ec.unmarshalInputExperimentRunFilterInput, - ec.unmarshalInputExperimentRunPhaseRequest, ec.unmarshalInputExperimentRunRequest, ec.unmarshalInputExperimentRunSortInput, ec.unmarshalInputExperimentSortInput, @@ -4919,27 +4904,6 @@ type Weightages { weightage: Int! } - -input ExperimentRunPhaseRequest { - projectID: ID! - - """ - ID of the infra infra in which the experiment is running - """ - infraID: InfraIdentity! - - """ - ID of the experiment run which is to be queried - """ - experimentRunID: String! - - """ - notifyID is required to give an ack for non cron experiment execution - """ - notifyID: String -} - - """ Defines the details of a experiment run """ @@ -5398,7 +5362,7 @@ type Mutation { """ Returns experiment run based on experiment run ID """ - getExperimentRun(projectID: ID!, experimentRunID: ID, notifyID: ID): ExperimentRun! + getExperimentRun(projectID: ID!, experimentRunID: ID, notifyID: ID, infraID: InfraIdentity): ExperimentRun! """ Returns the list of experiment run based on various filter parameters @@ -5412,7 +5376,6 @@ type Mutation { Query to get experiment run stats """ getExperimentRunStats(projectID: ID!): GetExperimentRunStatsResponse! - getExperimentRunPhase(request: ExperimentRunPhaseRequest!): ExperimentRun! } extend type Mutation { @@ -9313,21 +9276,6 @@ func (ec *executionContext) field_Query_getEnvironment_args(ctx context.Context, return args, nil } -func (ec *executionContext) field_Query_getExperimentRunPhase_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 model.ExperimentRunPhaseRequest - if tmp, ok := rawArgs["request"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("request")) - arg0, err = ec.unmarshalNExperimentRunPhaseRequest2githubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRunPhaseRequest(ctx, tmp) - if err != nil { - return nil, err - } - } - args["request"] = arg0 - return args, nil -} - func (ec *executionContext) field_Query_getExperimentRunStats_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -9373,6 +9321,15 @@ func (ec *executionContext) field_Query_getExperimentRun_args(ctx context.Contex } } args["notifyID"] = arg2 + var arg3 *model.InfraIdentity + if tmp, ok := rawArgs["infraID"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("infraID")) + arg3, err = ec.unmarshalOInfraIdentity2ᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐInfraIdentity(ctx, tmp) + if err != nil { + return nil, err + } + } + args["infraID"] = arg3 return args, nil } @@ -28678,7 +28635,7 @@ func (ec *executionContext) _Query_getExperimentRun(ctx context.Context, field g }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().GetExperimentRun(rctx, fc.Args["projectID"].(string), fc.Args["experimentRunID"].(*string), fc.Args["notifyID"].(*string)) + return ec.resolvers.Query().GetExperimentRun(rctx, fc.Args["projectID"].(string), fc.Args["experimentRunID"].(*string), fc.Args["notifyID"].(*string), fc.Args["infraID"].(*model.InfraIdentity)) }) if err != nil { ec.Error(ctx, err) @@ -28899,111 +28856,6 @@ func (ec *executionContext) fieldContext_Query_getExperimentRunStats(ctx context return fc, nil } -func (ec *executionContext) _Query_getExperimentRunPhase(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_getExperimentRunPhase(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.Query().GetExperimentRunPhase(rctx, fc.Args["request"].(model.ExperimentRunPhaseRequest)) - }) - 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.(*model.ExperimentRun) - fc.Result = res - return ec.marshalNExperimentRun2ᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRun(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_getExperimentRunPhase(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "projectID": - return ec.fieldContext_ExperimentRun_projectID(ctx, field) - case "experimentRunID": - return ec.fieldContext_ExperimentRun_experimentRunID(ctx, field) - case "experimentType": - return ec.fieldContext_ExperimentRun_experimentType(ctx, field) - case "experimentID": - return ec.fieldContext_ExperimentRun_experimentID(ctx, field) - case "weightages": - return ec.fieldContext_ExperimentRun_weightages(ctx, field) - case "updatedAt": - return ec.fieldContext_ExperimentRun_updatedAt(ctx, field) - case "createdAt": - return ec.fieldContext_ExperimentRun_createdAt(ctx, field) - case "infra": - return ec.fieldContext_ExperimentRun_infra(ctx, field) - case "experimentName": - return ec.fieldContext_ExperimentRun_experimentName(ctx, field) - case "experimentManifest": - return ec.fieldContext_ExperimentRun_experimentManifest(ctx, field) - case "phase": - return ec.fieldContext_ExperimentRun_phase(ctx, field) - case "resiliencyScore": - return ec.fieldContext_ExperimentRun_resiliencyScore(ctx, field) - case "faultsPassed": - return ec.fieldContext_ExperimentRun_faultsPassed(ctx, field) - case "faultsFailed": - return ec.fieldContext_ExperimentRun_faultsFailed(ctx, field) - case "faultsAwaited": - return ec.fieldContext_ExperimentRun_faultsAwaited(ctx, field) - case "faultsStopped": - return ec.fieldContext_ExperimentRun_faultsStopped(ctx, field) - case "faultsNa": - return ec.fieldContext_ExperimentRun_faultsNa(ctx, field) - case "totalFaults": - return ec.fieldContext_ExperimentRun_totalFaults(ctx, field) - case "executionData": - return ec.fieldContext_ExperimentRun_executionData(ctx, field) - case "isRemoved": - return ec.fieldContext_ExperimentRun_isRemoved(ctx, field) - case "updatedBy": - return ec.fieldContext_ExperimentRun_updatedBy(ctx, field) - case "createdBy": - return ec.fieldContext_ExperimentRun_createdBy(ctx, field) - case "notifyID": - return ec.fieldContext_ExperimentRun_notifyID(ctx, field) - case "runSequence": - return ec.fieldContext_ExperimentRun_runSequence(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type ExperimentRun", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_getExperimentRunPhase_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return fc, err - } - return fc, nil -} - func (ec *executionContext) _Query_getInfra(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_getInfra(ctx, field) if err != nil { @@ -36524,54 +36376,6 @@ func (ec *executionContext) unmarshalInputExperimentRunFilterInput(ctx context.C return it, nil } -func (ec *executionContext) unmarshalInputExperimentRunPhaseRequest(ctx context.Context, obj interface{}) (model.ExperimentRunPhaseRequest, error) { - var it model.ExperimentRunPhaseRequest - asMap := map[string]interface{}{} - for k, v := range obj.(map[string]interface{}) { - asMap[k] = v - } - - fieldsInOrder := [...]string{"projectID", "infraID", "experimentRunID", "notifyID"} - for _, k := range fieldsInOrder { - v, ok := asMap[k] - if !ok { - continue - } - switch k { - case "projectID": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("projectID")) - data, err := ec.unmarshalNID2string(ctx, v) - if err != nil { - return it, err - } - it.ProjectID = data - case "infraID": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("infraID")) - data, err := ec.unmarshalNInfraIdentity2ᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐInfraIdentity(ctx, v) - if err != nil { - return it, err - } - it.InfraID = data - case "experimentRunID": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("experimentRunID")) - data, err := ec.unmarshalNString2string(ctx, v) - if err != nil { - return it, err - } - it.ExperimentRunID = data - case "notifyID": - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("notifyID")) - data, err := ec.unmarshalOString2ᚖstring(ctx, v) - if err != nil { - return it, err - } - it.NotifyID = data - } - } - - return it, nil -} - func (ec *executionContext) unmarshalInputExperimentRunRequest(ctx context.Context, obj interface{}) (model.ExperimentRunRequest, error) { var it model.ExperimentRunRequest asMap := map[string]interface{}{} @@ -42793,28 +42597,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) - case "getExperimentRunPhase": - 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._Query_getExperimentRunPhase(ctx, field) - if res == graphql.Null { - atomic.AddUint32(&fs.Invalids, 1) - } - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, - func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) - } - out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "getInfra": field := field @@ -44766,11 +44548,6 @@ func (ec *executionContext) marshalNExperimentRun2ᚖgithubᚗcomᚋlitmuschaos return ec._ExperimentRun(ctx, sel, v) } -func (ec *executionContext) unmarshalNExperimentRunPhaseRequest2githubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRunPhaseRequest(ctx context.Context, v interface{}) (model.ExperimentRunPhaseRequest, error) { - res, err := ec.unmarshalInputExperimentRunPhaseRequest(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) unmarshalNExperimentRunRequest2githubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐExperimentRunRequest(ctx context.Context, v interface{}) (model.ExperimentRunRequest, error) { res, err := ec.unmarshalInputExperimentRunRequest(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -46744,6 +46521,14 @@ func (ec *executionContext) unmarshalOInfraFilterInput2ᚖgithubᚗcomᚋlitmusc return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalOInfraIdentity2ᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐInfraIdentity(ctx context.Context, v interface{}) (*model.InfraIdentity, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputInfraIdentity(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOInfrastructureType2ᚕᚖgithubᚗcomᚋlitmuschaosᚋlitmusᚋchaoscenterᚋgraphqlᚋserverᚋgraphᚋmodelᚐInfrastructureType(ctx context.Context, v interface{}) ([]*model.InfrastructureType, error) { if v == nil { return nil, nil diff --git a/chaoscenter/graphql/server/graph/model/models_gen.go b/chaoscenter/graphql/server/graph/model/models_gen.go index 217dc72e667..470b2690b1f 100644 --- a/chaoscenter/graphql/server/graph/model/models_gen.go +++ b/chaoscenter/graphql/server/graph/model/models_gen.go @@ -646,16 +646,6 @@ type ExperimentRunFilterInput struct { InfraTypes []*InfrastructureType `json:"infraTypes,omitempty"` } -type ExperimentRunPhaseRequest struct { - ProjectID string `json:"projectID"` - // ID of the infra infra in which the experiment is running - InfraID *InfraIdentity `json:"infraID"` - // ID of the experiment run which is to be queried - ExperimentRunID string `json:"experimentRunID"` - // notifyID is required to give an ack for non cron experiment execution - NotifyID *string `json:"notifyID,omitempty"` -} - // Defines the details for a experiment run type ExperimentRunRequest struct { // ID of the experiment diff --git a/chaoscenter/subscriber/pkg/graphql/operations.go b/chaoscenter/subscriber/pkg/graphql/operations.go index 50da9b90e3a..f6fa8e89a71 100644 --- a/chaoscenter/subscriber/pkg/graphql/operations.go +++ b/chaoscenter/subscriber/pkg/graphql/operations.go @@ -72,10 +72,9 @@ func (gql *subscriberGql) SendExperimentRunRuquest(infraData map[string]string, } func (gql *subscriberGql) GenerateExperimentRunPayload(cid, accessKey, version string, podLog types.PodLogRequest) ([]byte, error) { - infraID := `{infraID: \"` + cid + `\", version: \"` + version + `\", accessKey: \"` + accessKey + `\"}` - query := `{ infraID: ` + infraID + `, experimentRunID:\"` + podLog.ExperimentRunID + `\", projectID: \"` + podLog.ProjectID + `\", notifyID: \"\"}` - - var payload = []byte(`{"query":"query { getExperimentRunPhase(request:` + query + `){phase}}"}`) + infraID := `infraID: {infraID: \"` + cid + `\", version: \"` + version + `\", accessKey: \"` + accessKey + `\"}` + query := infraID + `, experimentRunID: \"` + podLog.ExperimentRunID + `\", projectID: \"` + podLog.ProjectID + `\", notifyID: \"\"` + var payload = []byte(`{"query": "query { getExperimentRun(` + query + `) { phase } }"}`) return payload, nil } diff --git a/chaoscenter/subscriber/pkg/k8s/log.go b/chaoscenter/subscriber/pkg/k8s/log.go index 015574f07af..4a8aa3dd1d2 100644 --- a/chaoscenter/subscriber/pkg/k8s/log.go +++ b/chaoscenter/subscriber/pkg/k8s/log.go @@ -117,7 +117,7 @@ func (k8s *k8sSubscriber) GetPodLogs(infraData map[string]string, podLog types.P // fetch ExperimentRun Phase from graphql experimentRun, _ := k8s.gqlSubscriberServer.SendExperimentRunRuquest(infraData, podLog) - logDetails.MainPod = k8s.categorizeLogByPhase(experimentRun.Data.ExperimentRun.Phase) + logDetails.MainPod = k8s.categorizeLogByPhase(experimentRun.Data.ExperimentRun.Phase) + " Pod name: " + podLog.PodName logrus.WithError(err).Print("Failed to get pod logs for attempting to fetch experiment run phase") @@ -140,25 +140,25 @@ func (k8s *k8sSubscriber) GetPodLogs(infraData map[string]string, podLog types.P func (k8s *k8sSubscriber) categorizeLogByPhase(phase string) string { switch phase { case "Completed": - return "Experiment pod is deleted" + return "Experiment pod was deleted." case "Stopped": - return "Stopped" + return "Experiment is stopped." case "Running": - return "Workflow Pod is initializing" + return "Experiment pod is initializing." case "Queue": - return "Queue" + return "Queue." case "NA": - return "NA" + return "NA." case "Terminated": - return "Terminated" + return "Terminated." case "Completed_With_Error": - return "Completed_With_Error" + return "Completed_With_Error." case "Timeout": - return "Timeout" + return "Timeout." case "Error": - return "it can't run experiment" + return "Experiment could not start." default: - return "Workflow Pod is initializing" + return "Experiment pod is initializing." } } diff --git a/chaoscenter/subscriber/pkg/types/graphql.go b/chaoscenter/subscriber/pkg/types/graphql.go index f5dd8fe85c7..1e1c29a7916 100644 --- a/chaoscenter/subscriber/pkg/types/graphql.go +++ b/chaoscenter/subscriber/pkg/types/graphql.go @@ -5,7 +5,7 @@ type ExperimentRunResponse struct { } type ExperimentRun struct { - ExperimentRun Phase `json:"getExperimentRunPhase"` + ExperimentRun Phase `json:"getExperimentRun"` } type Phase struct {